set 里用元素的equals方法区分元素,Object默认的equals比较的是内存地址,那就是通过 == 比较的
定义对象时,重写了equals方法,那么比对元素的方式就按照equals定义的方式来了
假如equals中按照元素的id 属性比对,id相同就认为元素相同,那么相同id的元素便只能一个入set了
定义对象时,重写了equals方法,那么比对元素的方式就按照equals定义的方式来了
假如equals中按照元素的id 属性比对,id相同就认为元素相同,那么相同id的元素便只能一个入set了
public class HashSet<E> extends AbstractSet<E>
implements Set<E>, Cloneable, Serializable
{
static final long serialVersionUID = -5024744406713321676L;
private transient HashMap<E, Object> map;
private static final Object PRESENT = new Object(); public HashSet()
{
this.map = new HashMap();
}HashSet组合了一个HashMap通过对HashMap的操作来实现哈希set。
hashset的add操作如下: public boolean add(E paramE)
{
return (this.map.put(paramE, PRESENT) == null);
}
可以看到操作这个map,所以set的唯一性其实靠的是hashmap,那么hashmap是如何保持的呢,看下源码: public V put(K paramK, V paramV)
{
if (paramK == null)
return putForNullKey(paramV);
int i = hash(paramK.hashCode());
int j = indexFor(i, this.table.length);
<span style="font-weight: bold;"> for (Entry localEntry = this.table[j]; localEntry != null; localEntry = localEntry.next)
if (localEntry.hash == i)
{
java.lang.Object localObject1;
if (((localObject1 = localEntry.key) == paramK) || (paramK.equals(localObject1)))
{
java.lang.Object localObject2 = localEntry.value;
localEntry.value = paramV;
localEntry.recordAccess(this);
return localObject2;
}
}</span>
this.modCount += 1;
addEntry(i, paramK, paramV, j);
return null;
}