参考文章:https://blog.csdn.net/qq_27093465/article/details/52207135
根据这篇文章整理归纳有些小小的增加 做了一个思维导图:
底层是一个数组+链表+红黑树的结构
当有新的元素插入的时候,会对key进行hash(),高位运算,取模运算(因为数组的长度永远都是2的几次幂,所以相当于对数组长度-1 求&),从而得出数组下标。
判断一下当前数组是否为空,如果是空,直接插入,如果存在,直接覆盖。否则,说明发生了碰撞,先判断一下是不是红黑树,不是的话遍历链表,准备插入。如果连遍长度大于8,转换成红黑树插入键值对。否则遍历插入。
插入以后判断长度 ++size是否>threshold 如果大于,则扩容。
扩容前要注意潘敦当前数组大小,如果已经超过最大 那么就不扩容
初始化一个数组,并将旧数组所有元素拷贝到新数组中。
jdk8做了一个优化
判断新增的一位是0还是1(扩容后,length变为原来的2倍,左移一位,判断这一位上的hashcode是0还是1 ,如果是0,索引不变,如果是1,索引变为原索引+原长度)
另外在插入的resize的时候,会出现一种环链。
其他未补充
1.List 和 Set 区别
list:元素有序放入,可重复。支持for循环,可以通过下标来遍历,也可以使用迭代器。
set:元素无序放入,不可重复,重复元素会覆盖掉。只能使用迭代器,因为它是无序的,无法用下标来取得想要的值。
(注意,set中放入的元素在我们看来虽然是无序的,但是其实它的位置是由该元素的HashCode决定的,是固定的,加入set的Object必须定义equals()方法)
2.List 和 Map 区别
List接口:继承自collection接口,是一个单列集合。
Map接口:顶级接口,是一个双列集合。
3.ArrayList 与 LinkedList区别
(1)ArraList是基于动态数组(全部拷贝,1.5倍)。LinkedList是双向链表结构(查一半)
(2)ArrayList查询快,增删慢。LinkedList查询慢,增删快。
4.ArrayList 与 Vector 区别(不谈)
5.HashMap 和 HashTable 区别
(1)HashMap是支持null key 和 null value的。在传入key传入null的时候,做了特殊处理,使其hashcode为0。HashTable是不支持的。
(2)在扩容机制上,HashMap会扩容为2的n+1次幂。HashTable会扩容为2n+1。
也就是说HashTable会尽量使用素数、奇数。而HashMap则总是使用2的幂作为哈希表的大小。我们知道当哈希表的大小为素数时,简单的取模哈希的结果会更加均匀(具体证明,见这篇文章),所以单从这一点上看,HashTable的哈希表大小选择,似乎更高明些。但另一方面我们又知道,在取模计算时,如果模数是2的幂,那么我们可以直接使用位运算来得到结果,效率要大大高于做除法。所以从hash计算的效率上,又是HashMap更胜一筹。
正如我们所言,HashMap由于使用了2的幂次方,所以在取模运算时不需要做除法,只需要位的与运算就可以了。但是由于引入的hash冲突加剧问题,HashMap在调用了对象的hashCode方法之后,又做了一些位运算在打散数据。
(3)线程安全,HashTable是线程安全的,而HashMap不是线程安全的。
6.HashSet 和 HashMap的区别
HashSet实现了Set接口。底层是基于HashMap实现的,set中的值相当于map中的key,又一个虚拟的object对象放入map中作为value
HashMap实现了Map接口。
7.HashMap和concurrentHashMap的区别
HashMap线程不安全
concurrentHashMap是线程安全的
9.ConcurrentHashMap 的工作原理及代码实现