开发者社区> 问答> 正文

HashMap底层机制是什么?

HashMap底层机制是什么?

展开
收起
芯在这 2021-12-14 22:09:56 713 0
1 条回答
写回答
取消 提交回答
  • HashMap底层其实是一个k-v结构的Entry数组,同时为了解决hash冲突问题,也存在链表结构。另外在1.8版本之后,为了优化链表结构,又引入红黑树,使得数据存储更加合理。

    jdk1.8之前,hashmap的默认数组长度为16,扩容机制如下

    (1)、就是hashmap在存值的时候(默认大小为16,负载因子0.75,阈值12),可能达到最后存满16个值的时候,再存入第17个值才会发生扩容现象,因为前16个值,每个值在底层数组中分别占据一个位置,并没有发生hash碰撞。

    (2)、当然也有可能存储更多值(超多16个值,最多可以存26个值)都还没有扩容。原理:前11个值全部hash碰撞,存到数组的同一个位置(这时元素个数小于阈值12,不会扩容),后面所有存入的15个值全部分散到数组剩下的15个位置(这时元素个数大于等于阈值,但是每次存入的元素并没有发生hash碰撞,所以不会扩容),前面11+15=26,所以在存入第27个值的时候才同时满足上面两个条件,这时候才会发生扩容现象。

    jdk1.8及其以后,hashmap的默认数组长度为64,扩容机制如下

    (1)、因为扩容比较消耗资源,所以应该尽量避免。但是在链表结构中,如果链表长度过长,会极大影响数据的查改效率,因此引入性能更加均衡的红黑树。

    (2)、扩大数组长度也是为了减少扩容机制的触发,其负载因子与jdk1.8之前一样为0.75。但是不同于jdk1. 7,放入key之前先扩容,放入后不重新判断是否扩容。达到阀值且hash冲突时才扩容。不发生hash冲突,可超过阀值。因此jdk1.7最多存个数:threshold+table.length-1,如介绍1。jdk1.8中,放入key之后再判断是否达到阈值,超过阈值就扩容,与是否hash冲突无关,因此最多存放key个数与阀值相同。

    jdk1.8中hash“冲突”时的解决方案

    (1)、如果冲突数量小于8,则是以链表方式解决冲突。

    (2)、而当冲突大于等于8时,就会将冲突的Entry转换为红黑树进行存储。

    (3)、而又当数量小于6时,则又转化为链表存储。

    2021-12-14 22:10:18
    赞同 展开评论 打赏
问答标签:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载