HashMap源码学习

  1. Lru的意思是先淘汰时间最远的哪一个,LFU则淘汰使用频率最小的哪一个。
  2. Hashmap

static int indexFor(int h, int length) {
return h & (length-1);
}
相当于%但length要是2的幂。

  • hashCode()用来确定对象在hashmap中的位置,函数返回一个整数,如果a.equals(b)a.hashCode()==b.hashCode()这两个函数一个用来确定对象是否相等,一个在hashMap中区分元素。hashCode()equals()的默认实现相似是内存地址。
for (Entry<K,V> e = table[0]; e != null; e = e.next) {    
            if (e.key == null) {    
                V oldValue = e.value;    
                e.value = value;    
                e.recordAccess(this);    
                return oldValue;    
            }    
    这个table[0]位置不光存了key==null的值,别的key也可能hash到这个位置
 void transfer(Entry[] newTable) {    
        Entry[] src = table;    
        int newCapacity = newTable.length;    
        for (int j = 0; j < src.length; j++) {    
            Entry<K,V> e = src[j];    
            if (e != null) {    
                src[j] = null;    
                do {    
                    Entry<K,V> next = e.next;    
                    int i = indexFor(e.hash, newCapacity);    
                    e.next = newTable[i];    
                    newTable[i] = e;    
                    e = next;    
                } while (e != null);    
            }    
        }    
    }    


 - 重新计算每个元素在表中的位置因为hash()%length中的length发生了变化并不是只要将table[i]中的一串列表直接移到newTable[i]中就行了。
 - table[i]中是单链表以null结尾
final Entry<K,V> removeMapping(Object o) {    
        if (!(o instanceof Map.Entry))    
            return null;    

        Map.Entry<K,V> entry = (Map.Entry<K,V>) o;    
        Object key = entry.getKey();    
        int hash = (key == null) ? 0 : hash(key.hashCode());    
        int i = indexFor(hash, table.length);    
        Entry<K,V> prev = table[i];    
        Entry<K,V> e = prev;    

        // 删除链表中的“键值对e”    
        // 本质是“删除单向链表中的节点”    
        while (e != null) {    
            Entry<K,V> next = e.next;    
            if (e.hash == hash && e.equals(entry)) {    
                modCount++;    
                size--;    
                if (prev == e)    
                    table[i] = next;    
                else   
                    prev.next = next;    
                e.recordRemoval(this);    
                return e;    
            }    
            prev = e;    
            e = next;    
        }    

        return e;    
    }    


  这个函数要是在双链表的实现中就可以直接删除了不用再找了。
  • 快速失败 fast-fail防止别的线程改变了表的结构
 final Entry<K,V> nextEntry() {    
            if (modCount != expectedModCount)    
                throw new ConcurrentModificationException();    
            Entry<K,V> e = next;    
            if (e == null)    
                throw new NoSuchElementException();    

            // 注意!!!    
            // 一个Entry就是一个单向链表    
            // 若该Entry的下一个节点不为空,就将next指向下一个节点;    
            // 否则,将next指向下一个链表(也是下一个Entry)的不为null的节点。    
            if ((next = e.next) == null) {    
                Entry[] t = table;    
                while (index < t.length && (next = t[index++]) == null)    
                    ;    
            }    
            current = e;    
            return e;    
        }    
始终保持next为下一个,那么获取下一个就是返回next,next跟新为next的下一个。hasNext()就是检测next是否为null这种设计主要是为了hasNext();

  • 迭代器定义在hashMap内部他的构造函数为private所以只能有hashMap调用,迭代器由于是hashMap的内部类,可以之间操纵hashMap的内部结构,而next()方法由于生命为public可以被外部调用。

3、HashMap共有四个构造方法。构造方法中提到了两个很重要的参数:初始容量和加载因子。这两个参数是影响HashMap性能的重要参数,其中容量表示哈希表中槽的数量(即哈希数组的长度),初始容量是创建哈希表时的容量(从构造函数中可以看出,如果不指明,则默认为16),加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度,当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 resize 操作(即扩容)。
文/Maat红飞(简书作者)
原文链接:http://www.jianshu.com/p/fc9e37ee2afd
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
4、HashMap中key和value都允许为null。
扩容是一个相当耗时的操作,因为它需要重新计算这些元素在新的数组中的位置并进行复制处理。因此,我们在用HashMap的时,最好能提前预估下HashMap中元素的个数,这样有助于提高HashMap的性能。

如果hashmap中有重复key则第二次插入讲第一次的value覆盖

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值