HashMap各个要素的原因

今天博主主要分享这些默认值的原因,也就是它为什么是这个值。

初始容量

Capacity:16
初始容量为16,为什么?

  1. 首先,选取为 2 n 2^n 2n原因是因为取模时直接hash&(length-1)进行运算,提高运算的速度,这也是为什么扩容时是 2 n 2^n 2n的原因。
  2. 其次,为什么是16呢?作为初始容量,太大了,浪费空间,太小了,放两个元素就需要扩容,所以16作为一个相对中间的经验值,就被选定了。

链表转化红黑树长度阈值

treeifyThreshlid:8
阈值为8,为什么?

Ideally, under random hashCodes, the frequency of nodes in bins follows a Poisson 
distribution with a parameter of about 0.5 on average for the default resizing threshold of 
0.75, although with a large variance because of resizing granularity. Ignoring variance,
 the expected occurrences of list size k are (exp(-0.5) pow(0.5, k) / factorial(k)). The first 
 values are:

      0:    0.60653066

      1:    0.30326533

      2:    0.07581633

      3:    0.01263606

      4:    0.00157952

      5:    0.00015795

      6:    0.00001316

      7:    0.00000094

      8:    0.00000006
  1. 理想状态下,Loadfactor为0.75时,桶中节点分布频率遵循入参为0.5的泊松分布。进而推出桶中链表长度的概率,当链表长度为8时,概率为0.00000006,这是非常低的。所以选用了8来作为阈值。当比7低时,链表的平均查找速度是可接受的,当链表转为红黑树时,空间会扩大两倍,但因为出现这个的概率是非常低的,那么如果出现这种情况,转为红黑树的空间是可接受的。
  2. 当阈值为8时,链表的平均查找为8/2=4,红黑树的平均查找为log8=3,查找速度更短,而且随着节点的增多,差距更明显。
    在这里插入图片描述

负载因子

loadFactor:0.75
负载因子为0.75,为什么?

  1. 当负载因在过大时,桶中发生碰撞的概率就越大,负载因子过小,那么存放几个元素就要扩容。0.75是一个折中的选择。
  2. 在理想状态下(hash分布均匀的条件)下,loadfactor=0.75的情况下,桶中节点的分布概率遵循泊松分布。而根据这个,也可得出为什么红黑树阈值为8。

红黑树转化容量阈值

min_treeify_capacity = 64
原因:是为了防止初始时拆入过多同一位置的元素导致没必要的转化。
为什么是64?
都是容量和时间的一个平衡,因为treeNode比node空间大一倍,

红黑树转链表阈值

untreeifyThreshold = 6
原因:
log6 = 2.6,6/2=3,查找接近,但是树更浪费空间,所以转换为链表。

数据分析

当数据是万级数据时,初始容量为16存入速度更快,8和32速度更慢
当数据在万级以上时,初始容量8更快,16,32较慢(创建表占主要时间)
当数据在万级以下时,32更快(扩容在主要消耗时间)

当数据在百万级以上时,初始容量在标准容量(数据量/3*4+1),速度较慢,体现不到优势,说明此时创建table占主要时间消耗
当数据在百万级一下时,标准容量时间更短。

HashMap内存泄漏的原因可能有以下几个方面: 1. 对象的生命周期过长:如果在HashMap中存储的对象的生命周期比HashMap本身还要长,那么这些对象就无法被GC回收,从而导致内存泄漏。 2. 键对象的重写hashCode和equals方法不一致:如果键对象重写了hashCode方法,但没有重写equals方法,或者重写了equals方法但没有重写hashCode方法,那么可能导致在HashMap内部出现链表形式的数据结构,从而导致内存泄漏。 3. 大量的resize操作:如果HashMap中的元素数量不断增加,导致HashMap需要不断进行resize操作,那么可能会占用大量的内存空间,从而导致内存泄漏。 4. 弱引用被意外回收:如果在HashMap中使用了弱引用,但是弱引用被意外回收,那么在HashMap中可能会出现key为null的情况,这会导致HashMap内存泄漏。 为了避免HashMap内存泄漏,可以采取以下措施: 1. 及时清理HashMap:在HashMap中存储的对象不再使用时,应该及时从HashMap中移除,以便让GC能够回收这些对象。 2. 重写hashCode和equals方法:在使用HashMap时,应该尽可能地重写键对象的hashCode和equals方法,以确保HashMap内部的数据结构能够尽可能地合理。 3. 指定HashMap的初始大小:在创建HashMap时,应该尽可能地指定HashMap的初始大小,以减少resize操作的次数。 4. 使用WeakHashMap:如果需要在HashMap中存储的对象的生命周期比HashMap本身还要短,可以考虑使用WeakHashMap,这样可以避免内存泄漏的情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值