MAP学习笔记
1. 常用MAP
常用的Map有:HashMap、HashTable、ConcureentHashMap
三者的继承树如下图:
2.MAP底层实现
由上图可见,MAP底层为数组+链表方式进行代码实现。
HashMap与ConcureentHashMap在JDK1.8中又加入了红黑树进行查询优化。
上图可见,如果之前数组中存储的数据类型为TreeNode,也就是红黑树,那么之后存储的数据类型都为TreeNode,如果数组长度大于7,将原数组重组,将Node数组转换为TreeNode数组。
获取Map元素时:
可以看出,如果数组内类型是链表,则从最后一个元素向前遍历查询,如果数组内类型是红黑树,则使用树查询。
3.HashMap的扩容机制
- 默认长度:DEFAULT_INITIAL_CAPACITY = 1 << 4。如果未指定map的长度,则系统默认16.
- 负载因子:DEFAULT_LOAD_FACTOR = 0.75f。数组内占用长度达到了数组lenth*0.75则进行重组扩容,每次扩容一倍。
JDK源码如下:
4.线程安全的Map
HashTable与ConcureentHashMap为线程安全的Map。
- HashTable是将所有操作数组的方法加上了synchronized。
- ConcureentHashMap是将方法内涉及操作数组的代码片段添加了synchronized。
ConcureentHashMap内的链表结构:
用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最的值。volatile很容易被误用,用来进行原子性操作。