ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java之HashMap要点

2021-11-25 01:00:31  阅读:155  来源: 互联网

标签:扩容 插法 Java HashMap 容量 元素 链表 要点 hash


  1. hash表容量确定:实例化一个hashMap,其容量设为n,最终hash数组的大小会分配不小于n,最小的2的整数次方的数。这个数的计算方式如下:
// 由于hash表的容量上限为int的最大值,亦即2的32次方,所以将n按16位,做高低分区。
// 对于n的二进制数,最高的为1的位置,向右排,若全为1,这个右侧全1对齐的数加上1,就是hash表的容量。
k = n - 1;
k_1 = k ^ 1;
k_2 = k_1 ^ 2;
k_3 = k_2 ^ 4;
k_4 = k_3 ^ 8;
k_5 = k_4 ^ 16;
//经过上述步骤计算后,得到的k_5就是n的低位全1值,k_5 + 1就是最中的hash表的容量。
  1. 为何hash表的物理容量要定为2的幂?2的幂减去1后,得到的二进制数右侧是1对齐的,对于put和get操作时的点位计算,正好可以作为掩码用,方便实施与运算,比取模运算更高效。
  2. map总容量大于64,且链表长度大于8时,链表转化为红黑树。因为链表的查询时间复杂度是O(n),红黑树是平衡二叉查找树,查询时间复杂度为O(log(n)。当红黑树的元素个数小于6时,又会转回链表。
  3. 默认负载因子为0.75,兼顾如下两个因素:
  • hash碰撞概率:根据泊松分布,当负载因子大于0.75时,hash碰撞的概率会显著升高。

  • 内存空间利用率:负载因子越小,碰撞率越低,但是会造成更多的空间浪费,所以,0.75是一个平衡两者的结果。

  1. 链表头插法与尾插法:
  • 头插法:因为可以直接找到一个链表的头元素O(1),不需要遍历任何元素,故头插法最高效。若扩容后还同链,元素间的相对顺序会发生翻转。

  • 尾插法:因为需要从头遍历一个链表中的所有元素,才能找到其尾元素,然后才能追加新元素,时间复杂度为O(n),所以,尾插法的效率较低。若扩容后仍同链,元素间的相对顺序不变。

  • 并发扩容时:

    1. 设原顺序为:a -> b
    2. 线程1持有元素a,还没来得及做扩容操作,就被挂起了。
    3. 就在此时,线程2顺利的完成了扩容,此时的链表顺序被翻转了:b -> a。
    4. 线程1被唤醒,拿着手里的a继续它的扩容过程,往新链表上以头插法存a,发现b是头元素,就将a的next设为b,环就形成了,此时顺序是a -> b -> a。带环的链表会导致死循环。
  1. hash定位算法实现
//hashCode是一个int值,一个32位的数。
//把hashCode分为各16位的高低两个区,然后让这两块进行异或运算,名曰“扰动函数”。
//扰动函数的作用,降低碰撞率,均匀,位运算高效。

//由于直接用hashCode同(n - 1)做与运算,只用到了hashCode的低位区,碰撞概率必然增大,进过一次扰动函数计算,能使定位更分散。
  1. jdk1.8的优化
  1. put时,1.7先判断是否需要扩容再写入,1.8则是先写入在判断是否需要扩容。
  2. 扩容时,1.7将所有元素通通rehash一遍,1.8则是要么原位置安放,要么原容量 + 原索引值安放。
  3. 1.7、1.8都不是线程安全的,1.7会形成死循环、数据丢失、数据覆盖,1.8会发生数据覆盖。
  1. 链表转红黑树的长度阈值为什么是8,不是16,32甚至是7呢?又为什么红黑树转链表的阈值是6,而不是8呢?
  1. 经统计,在hash函数设计合理的情况下,发生hash碰撞8次的几率为百万分之6,从概率看,8够用了。
  2. 至于为什么转回来是6,因为如果hash碰撞次数在8附近徘徊,会频繁发生链表和红黑树的转化,为了预防这种情况的发生。

标签:扩容,插法,Java,HashMap,容量,元素,链表,要点,hash
来源: https://www.cnblogs.com/JaxYoun/p/15601010.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有