HashMap:
(1)JDK1.8以后 HashMap的数据结构发生了一些改变,从单纯的数组加链表结构变成数组+链表+红黑树.
(2)Node是HashMap的一个内部类,实现Map.Entry接口,本质是一个KV映射,每个元素都是一个Node对象. HashMap顾名思义是通过Hash表进行存储.为了解决哈希碰撞的问题,Java采用这种数组 + 链表方式来进行存储.
(3)HashMap在JDK1.8中采用,数组+链表+红黑树 组成。根据key的索引 ( (n - 1) & hash)判断节点位置,同一节点中的数据非一个时: 个数大于 树化阈值(TREEIFY_THRESHOLD ) 8 时,节点内存储结构为红黑树, 当红黑树节点个数小于 6 时,又会转化成链表。
TreeNode链表修改红黑树:
final void treeify(Node<K,V>[] tab) {//做树
TreeNode<K,V> root = null;
for (TreeNode<K,V> x = this, next; x != null; x = next) {
next = (TreeNode<K,V>)x.next;//记录x.next,使得下一轮x=x.next遍历
//x 为当前要插入树中的数据
x.left = x.right = null;
if (root == null) {//根节点
x.parent = null;
x.red = false;
root = x;
}
else {
K k = x.key;//当前要插入的树节点的key
int h = x.hash;//当前节点的hash
Class<?> kc = null;
for (TreeNode<K,V> p = root;;) {
//从根节点开始遍历 p,p要跟x比较,才能找到x要插到树的哪个位置
int dir, ph;//dir:方向 ph:当前被比较的p的hashcode
K pk = p.key;
if ((ph = p.hash) > h)//如果p的hash值大于x的hash值,则dir为-1
dir = -1;
else if (ph < h)//如果p的hash值小于x的hash值,则dir为1
dir = 1;
else if ((kc == null &&//当p和x的hash值一样,且没有可比较时
(kc = comparableClassFor(k)) == null) ||//是否有实现comparable接口
(dir = compareComparables(kc, k, pk)) == 0)//
dir = tieBreakOrder(k, pk);//当无法比较时,使用自带的比较方法。当k和pk 的classname相同,就调用比较k和pk的原始hashcode。
TreeNode<K,V> xp = p;
if ((p = (dir <= 0) ? p.left : p.right) == null) {
x.parent = xp;
if (dir <= 0)
xp.left = x;
else
xp.right = x;
//保持红黑树并插入数据,
root = balanceInsertion(root, x);
break;
}
}
}
}//Ensures that the given root is the first node of its bin.
moveRootToFront(tab, root);
}