前言
正文
本文用jdk版本:1.8.0_181 和1.7
1.8版本
构造方法
1 |
|
注意:
- 这里并没有一开始就初始化容器中的数组,只是将传入的数量赋值给threshold;
- 还需要注意的是tableSizeFor这个方法,这个方法会自动将传入的值改变为一个为2整数次幂的一个整数;
添加方法
1 |
|
注意:
- 注意这里的hash方法,key为null会返回0,HashMap可以存null 的key就是在这里体现的;
第二个方法:
1 |
|
注意:
- 注意resize方法,该方法实现将容器真正的初始化和扩容
- 容器中的红黑树是用TreeNode实现的
- 这里的链表插入是插入末尾
- 判断是否将链表转为红黑树是根据TREEIFY_THRESHOLD这个属性来判断的,转换调用的方法是treeifyBin
- afterNodeAccess和afterNodeInsertion这两个方法是LinkedHashMap实现的,需要去了解LinkedHashMap;因为存入对象在容器中存在,所以会调用afterNodeAccess方法,将存入的对象对应的节点排到最后,表示刚使用过;因为存入的对象在容器中不存在,所以是加入了一个节点,所以调用afterNodeInsertion方法,会去掉LinkedHashMap中的头节点;
resize方法
该方法主要是初始化或扩容的
1 |
|
注意:
- 原来数组中的数据放到新数组中,只会存在两个节点中;
- 扩容是变为原来的两倍,是数组长度扩容
treeifyBin 方法
1 |
|
注意:
- 链表转红黑树并不是链表长度达到8之后就可以,而是还需要数组长度也达到64以上
get方法
1 |
|
getNode方法
1 |
|
put流程图
get流程图
1.7与 1.8比较
-
数据结构
1.7使用数组加链表的数据结构,1.8使用数组,链表加红黑树的数据结构 -
初始化以及扩容
1.7使用 -
数据插入方式
1.7使用头插法,将数据插入头节点;1.8使用尾插法,将数据插入链表末尾,即便是扩容也是尾插法 -
hash计算方式
1.8使用了一次位运算加一次异或运算;1.7进行了四次位运算加五次异或运算;