`
liaokang.java
  • 浏览: 152139 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
社区版块
存档分类
最新评论

HashMap底层的实现

    博客分类:
  • java
 
阅读更多
首先我们来看看HashMap的底层源码
    /**
     * Constructs an empty <tt>HashMap</tt> with the default initial capacity
     * (16) and the default load factor (0.75).
     */
    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR;
        threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
        table = new Entry[DEFAULT_INITIAL_CAPACITY];
        init();
    }

我们可以看到底层其实就是一个数组,而且是一个Entry类型的数组,我们来看看Entry类的源码
 static class Entry<K,V> implements Map.Entry<K,V> {
        final K key;
        V value;
        final int hash;
        Entry<K,V> next;

它是一个静态内部类,成员变量有我们放进去的key,value以及指向下一个Entry对象的引用当我们调用put方法时
    public V put(K key, V value) {
	K k = maskNull(key);
        int hash = hash(k);
        int i = indexFor(hash, table.length);

        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            if (e.hash == hash && eq(k, e.key)) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, k, value, i);
        return null;
    }


它首先根据key值生成一个hash值,并通过以下方法
  static int indexFor(int h, int length) {
        return h & (length-1);
    }


得到数组的存放位置,如果该位置已经有对象存在了,就顺着此对象的链开始寻找,如果e.hash == hash && eq(k, e.key)返回为真就用新的对象替换旧的对象并将旧的对象返回,如果都不成功,表示在链上不存在,这个时候就直接添加到数组,同时将添加的这个Entry的next指向被替换的那个Entry对象,实现如下
   void addEntry(int hash, K key, V value, int bucketIndex) {
	Entry<K,V> e = table[bucketIndex];
        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
        if (size++ >= threshold)
            resize(2 * table.length);
    }

总的来说HashMap底层是用数组来实现,而每一个数组元素又可以当成一个链表的头,这样做是为了提高查询的效率,使得查找时间不会随Map的大小而改变
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics