JavaSet的源码分析

来源:互联网 发布:js 手机版 个人收藏 编辑:程序博客网 时间:2024/05/23 14:31

Java中,set能保证列表中元素唯一,map就是用来key-value用的东西。

先看Set。

首先Set是个接口,最常见的实现有HashSet,LinkedHashSet,和同步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);  }
通过在hashmap中把要放到set中的元素作为key,静态变量present(Object类型)作为value,来为hashset添加元素。

同理,hashset的remove操作也就是对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);    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;        }      }    this.modCount += 1;    addEntry(i, paramK, paramV, j);    return null;  }
其中粗体标注了检测要添加的元素是否在map中的操作。这里用到了hashcode和equals的作用。hashcode在之前的文中已经提到过,是为了减少对对象的比较复杂度而设置的。这里遍历了map中所有的元素。

  transient Entry[] table;
上面粗体还提到了table属性。这里是维护的Entry的数组,同其他列表一样,数组大小会自动增长:不过奇怪的是,这里使用了2147483647这个数字,不知道那个if判断是做什么用的,求指点

  void resize(int paramInt)  {    Entry[] arrayOfEntry1 = this.table;    int i = arrayOfEntry1.length;    if (i == 1073741824)    {      this.threshold = 2147483647;      return;    }    Entry[] arrayOfEntry2 = new Entry[paramInt];    transfer(arrayOfEntry2);    this.table = arrayOfEntry2;    this.threshold = (int)(paramInt * this.loadFactor);  }





原创粉丝点击