set 里用元素的equals方法区分元素,Object默认的equals比较的是内存地址,那就是通过 == 比较的
定义对象时,重写了equals方法,那么比对元素的方式就按照equals定义的方式来了
假如equals中按照元素的id 属性比对,id相同就认为元素相同,那么相同id的元素便只能一个入set了

解决方案 »

  1.   

    Set 是接口,我们看下HashSet源码
    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;
      }
      

  2.   

    优先用hashcode,如果hashcode一样则看equals,equals相等则相等 equals不相等则不相等,如果hashcode不相等即使equals相等set也认为是不相等