hashmap转红黑树的阈值为8_HashMap数据结构剖析

书接上文,HashMap源码分析上文书对hashmap的源码做了一个简单的解析,这回我们来说一下HashMap的数据结构问题。

上文中说到HashMap的基础结构一个初始容量为16的数组,加载因子是0.75,也就是容量使用到12的时候会触发扩容机制,扩容后的容量为原来的2倍。

但这并不是说超过12个元素就会扩容,其实这里容量为16的数组并不只是一个简单的数组结构,而是数组在链表的结构。类似于下面图中这样的一个结构:

2f8a8dc0298c16c34b8cf49f63140f09.png

数组中的每个索引中包含的元素可能是多个,也就是可能>=0个元素。那么这个索引的值是怎么计算的呢?我们在源码可以看到

public V put(K key, V value) {

return putVal(hash(key), key, value, false, true);

}

其中hash函数的代码如下:

static final int hash(Object key) {

int h;

return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

}

即通过上面做对计算出key的hash值,然后我们在putVal()中可以看到如下的代码:

if ((tab = table) == null || (n = tab.length) == 0)

n = (tab = resize()).length;

if ((p = tab[i = (n - 1) & hash]) == null)

tab[i] = newNode(hash, key, value, null);

..........

其中关键代码是这句:

i = (n - 1) & hash

即,是通过key的hash值和容器的大小减1,两者进行与运算,获取容器数组下标。这里使用与运算,其实蕴含了一个隐藏条件,即数组的大小n,必须是2的n次方,否则,计算出来的下标值i是无法覆盖这个范围[0, n-1]的。这就是为什么每次扩容都是*2的原因。

而如果这个链表可以无限延长,那么毫无疑问会造成查询数据的性能问题,于是JDK1.8引入的红黑树,上文中提到的由链表转红黑树的阈值是8,也就是如果链表的长度到8就会转变成树结构。以此来解决链表过长而引发的性能问题。红黑树的存储结构大概如下:

2830f344932203feb6e693ed60e1a926.png

这里顺便推荐一个数据结构可视化的网站https://www.cs.usfca.edu/~galles/visualization,可以直观的了解红黑树和其它数据结构,也可以对比其它树结构,应该就能明白为何HashMap选用红黑树而不是其它的树型结构。这里就不再赘述。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值