HashMap与ConcurrentHashMap 的数据结构
HashMap:
数组与链表,每个数据对应一个链表
插入时进行与运算
http://blog.csdn.net/tingting256/article/details/52475422
数组默认长度16,当超过16*0.75=12时,组数长度变为16*2->叫resize,毁
HashMap的基础构造器HashMap(intinitialCapacity,floatloadFactor)带有两个参数,它们是初始容量initialCapacity和加载因子loadFactor。
https://www.cnblogs.com/ITtangtang/p/3948406.html
相同含义的两个对象,插入同一个key:
http://blog.csdn.net/zbuger/article/details/51029898
为什么数据是2的n次幂
为了更均匀打到槽点。与运算
http://www.cnblogs.com/ysocean/p/9054804.html
当lenth=2n时,X%length=X&(length-1),模运算%可以变换为按位与&运算
早期版本是直接取模%,后期改为位运算
一个十进制数对一个2n的数取余,我们可以将这个十进制转换为二进制数,将这个二进制数右移n位,移掉的这n位数即是余数。
为什么是数组长度是16
计算卡槽点时,具体落到哪个数组时,做与运算时
hash(hashCode(key))&(length-1)->会落到位置范围内
二进制:Interger.toBinaryString(15);
容量到了12会扩容:在扩容的时候更多的节点不需要重新计算到新槽点,hash之后的桶的角标是不变的。
为什么0.75
过低,小一点:扩容频繁。
过高,大一点:扩容不容易发生,数组重复概率增加,导致get和put时间增多,冲突需要遍历大量链表空间。
finalinthash(Objectkey)里有>>>,>>>
降低重复冲突概率
深入理解:https://www.zhihu.com/question/20733617
“扰动函数”混合原始哈希码的高位和低位,加大低位随机性,为了减少数组碰撞概率,减少10%。
Java8觉得扰动做一次就够了,做4次的话,多了可能边际效用也不大,所谓为了效率考虑就改成一次了。
当获取对象时get,hash找到数组槽位,循环链表,通过键对象key的equals()方法找到正确的键值对,然后返回值对象。
HashTable:
数组默认长度11
http://blog.csdn.net/xuefeng0707/article/details/40834595
继承的父类不同
线程安全性不同
key和value是否允许null值
hash值不同,插入算法也不同,hashtable取取模运算,hashmap与运算。
是否提供contains方法
http://blog.csdn.net/fujiakai/article/details/51585767
ConcurrentHashMap:
http://blog.csdn.net/yan_wenliang/article/details/51029372
segment数组,每个数组是一个hashtable,里面有分段锁
多线程put时,当同一数组存储时线程加锁,不同数组时,没有锁,效率的提升。