赞
踩
Java 中的 HashMap 采用链表法来解决哈希冲突HashMap 原理,即具有相同桶下标的键值对使用一个链表储存。当链表变长时,查找和添加(需要确定 key 是否已经存在)都需要遍历这个链表,速度会变慢。JDK 1.8 后加入了链表转换为红黑树的机制,但是红黑树的转换并不是一个廉价的操作,只有当链表长度大于等于 TREEIFY_THRESHOLD 才会 treeify。
/**
* The bin count threshold for using a tree rather than list for a
* bin. Bins are converted to trees when adding an element to a
* bin with at least this many nodes. The value must be greater
* than 2 and should be at least 8 to mesh with assumptions in
* tree removal about conversion back to plain bins upon
* shrinkage.
*/
static final int TREEIFY_THRESHOLD = 8;
TREEIFY_THRESHOLD 默认为 8,putVal()
源码如下:
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
实际上并不是只要链表长度大于 8 就会 treeify。当 table.length(桶的个数)小于 MIN_TREEIFY_CAPACITY 时会优先扩容而不是转换为红黑树。
以 jdk1.8 为例,打开 HashMap 的源码部分,红黑树内部类 TreeNode 属性分析:
static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
//指向父节点的指针
TreeNode<K,V> parent;
//指向左孩子的指针
TreeNode<K,V> left;
//指向右孩子的指针
TreeNode<K,V> right;
//前驱指针,跟next属性相反的指向
TreeNode<K,V> prev;
//是否为红色节点
boolean red;
......
}
左旋方法 rotateLeft 如下:
/* * 左旋逻辑 */ static <K,V> TreeNode<K,V> rotateLeft(TreeNode<K,V> root, TreeNode<K,V> p) { //root:表示根节点 //p:表示要调整的节点 //r:表示p的右节点 //pp:表示p的parent节点 //rl:表示p的右孩子的左孩子节点 TreeNode<K,V> r, pp, rl; //r判断,如果r为空则旋转没有意义 if (p != null && (r = p.right) != null) { //多个等号的连接操作从右往左看,设置rl的父亲为p if ((rl = p.right = r
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。