https://tech.meituan.com/2016/06/24/java-hashmap.html
比较 | HashMap | HashTable |
---|---|---|
key/value 是否为null | key 和 value 都可以为null | key 和 value 都不可以为null |
是否同步 | 不同步 | 同步 |
说一下HashMap的实现原理
HashMap的数据结构:数组 + 链表(红黑树),HashMap基于hash算法实现的,当我们往HashMap中put元素时,利用key的hashCode重新hash计算出当前对象的元素在数组中的下标。
存储时,如果出现hash值相同的key,此时有两种情况:
1.如果key相同,则覆盖原来的值;
2.如果key不同,也就是出现了冲突,则将当前的key-value放入链表中。
根据key获取时,同样是利用key的hashCode计算hash值对应的下标,再进一步判断key是否相同,从而找到对应值。
HashMap解决hash冲突的方式就是使用数组的存储方式,将冲突的key的对象放入链表中,一旦发现冲突就在链表中做进一步的对比。
在JDK1.8中对HashMap的实现做了优化,当链表中的节点数超过8个之后,该链表会转换为红黑树来提高查询效率,从原来的O(N)到O(logN)。
影响HashMap性能的两个参数
- initial capacity 初始容量,默认值 16
- load factor 负载因子,默认值 0.75
成员变量
1 | // 默认的初始容量16 |
构造方法
1 |
|
添加元素
1 | /** |
1 | /** |
1 | /** |
HashMap 是数组+链表数据结构组成的,那么数组的类型是什么
计算hash值
计算元素在数组中的位置
数组的长度
数组的类型Entry
Entry 类型的数组 和 Entry类型的链表
hash
key
value
next
如果key 值相同,hash值肯定相同,则直接替换值。
如果hash 值相同,key 不同,则放在链表中。
发生hash冲突时,jdk1.7头插法,jdk1.8尾插法。
阈值
threshold = capacity * load factor1
2
3
4
5
6
7
8
9
10
11
12
13
14
15/**
* Associates the specified value with the specified key in this map.
* If the map previously contained a mapping for the key, the old
* value is replaced.
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with <tt>key</tt>, or
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
* (A <tt>null</tt> return can also indicate that the map
* previously associated <tt>null</tt> with <tt>key</tt>.)
*/
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
1 | /** |
1 | /** |
使用HashMap的put操作,当容量大小超过阈值则发生扩容(调用resize()),在并发情况下可能会产生循环链表,在执行get的时候,可能会触发死循环,引起CPU 100%问题。
JDK8虽然修复了死循环的BUG,将原来的链表部分改为数据量少时用链表,当超过一定数量后变为红黑树(treeifyBin())。但是HashMap 还是非线程安全类,仍然会产生数据丢失等问题。
https://blog.csdn.net/mgl934973491/article/details/57405247
不同的key用同样的hash算法,可能会得到相同的hash值,比如Ab BB的hash值一样。
- 线性探测法
- 拉链法(HashMap中使用这种方法进行冲突处理的)
http://www.cnblogs.com/binyue/p/3726403.html
红黑树
平衡二叉树
结点是黑色或红色及诶单那
根结点是黑色
最长子树不能超过最短子树的2倍
每一条搜索路径有相同的黑色结点
任何一条路径不能连续出现两个相同的红色结点,所有叶子节点都是黑色
参考