参考
HashMap定义
- Hashmap由数组链表和红黑树构成,数组的初始长度是16,向数组中插入元素时如果产生hash冲突,会在产生冲突的位置生成链表,JDK1.7采用头插法,多线程时会出现死循环,JDK1.8采用尾插法可以避免死循环,如果链表的长度为8并且数组长度为64,会将链表转化成红黑树。如果数组长度小于64或者数组元素数量大于数组容量乘以0.75会进行扩容,扩容位原来长度的2倍。扩容后会将链表中的元素重新分配到新数组上,JDK1.7采用模运算,JDK1.8采用位运算,低位放到原来的位置,高位放的新位置,新位置的下标是元素的下标加上数组的长度
- 链表的时间复杂度是o(n),红黑树的时间复杂度是o(logn)
- 扩容因子小于0.75会导致频繁扩容,大于0.75会增加hash冲突
- 数组扩容为原来的2倍可以节约空间,减少hash冲突
- 数组扩容后为2的幂次方,可以提高运行速度减少hash冲突
- 链表的长度达到8会转成红黑树,红黑树的节点达到6会转成链表。
链表转红黑树的限制为何是8,红黑树转链表的限制为何是6
小于8时操作链表比操作红黑树开销小。限制为6可以避免频繁转换
HashTable以及ConcurrentHashMap对比
hashtable是全表锁,为每个方法都加锁,高并发下性能低已经过时了。ConcurrentHashMap是细颗粒度锁,为每个桶都加锁,高并发下性能高

如何使现有的HashMap线程安全
使用Collections.synchronizedMap /kəˈlɛkʃənz/(锁的是整个 Map 对象类似 Hashtable 的方式)
HashTable和ConcurrentHashMap在所有情况下都是线程安全的吗
不是,大多数场景下是线程安全的,复合操作时不是线程安全的。比如先判断Key是否存在,存在的话就调用put方法,在多线程的情况下会出现旧值覆盖新值的情况

43万+

被折叠的 条评论
为什么被折叠?



