hashMap的数组长度,加载因子及转红黑树的阈值解析

hashMap的数组长度为什么要求是2的整数次幂

为了能让 HashMap 存取高效,尽量较少碰撞,也就是要尽量把数据分配均匀。Hash 值的范围值-2147483648到2147483647,前后加起来大概40亿的映射空间,只要哈希函数映射得比较均匀松散,一般应用是很难出现碰撞的。但问题是一个40亿长度的数组,内存是放不下的。所以这个散列值是不能直接拿来用的。用之前还要先做对数组的长度取模运算,得到的余数才能用来要存放的位置也就是对应的数组下标。这个数组下标的计算方法是“ (n - 1) & hash ”。(n代表数组长度)。
这个算法应该如何设计呢?
我们首先可能会想到采用%取余的操作来实现。但是,重点来了:“取余(%)操作中如果除数是2的幂次则等价于与其除数减一的与(&)操作(也就是说 hash%length==hash&(length-1)的前提是 length 是2的 n 次方;)。” 并且 采
用二进制位操作 &,相对于%能够提高运算效率,这就解释了 HashMap 的长度为什么是2的幂次方。
下面这张图很好的解释了找到对应数组下标的过程。
拿16举例,16-1=15,15的二进制为1111,15&hash的得到哈希值的低四位,这个第四位刚好对应着16长度的0-15下标,而且实现了散列。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 在Java 8中,HashMap内部使用了数组和链表来实现键值对的存储。数组用来存储桶(bucket),每个桶下面会挂一个单向链表,用来存放键值对。 当链表长度超过8时,HashMap会将链表化为,以提高查找效率。而数组长度的选择则是为了在不同负因子下,保证不同的性能表现。 负因子是指HashMap中已经存储的键值对数量与数组长度之比。当负因子大于等于0.75时,HashMap会将数组长度扩大一倍,以减少哈希冲突的概率。因为随着数组长度的增,哈希冲突的概率会逐渐降低。 而当数组长度大于等于64时,每个桶的平均链表长度为8时,HashMap会将链表化为。这是因为,当链表长度较短时,使用链表比较快;但当链表长度过长时,查找效率会变得很低。而使用可以将查找时间从O(n)降低到O(log n),提高了HashMap的性能。具体的化条件可以看下面的代码: ``` static final int TREEIFY_THRESHOLD = 8; /** * 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 bin. */ static final int MIN_TREEIFY_CAPACITY = 64; ``` 在Java 8中,数组长度为2的整数次幂,这样可以通过位运算来计算哈希值对数组长度取模,提高效率。因此,数组长度为64是因为它既可以容纳足够多的键值对,也可以提供足够的桶数,同时在进行哈希运算时也比较高效。 ### 回答2: 在HashMap中,数组长度涉及到HashMap的扩容机制和换条件。 首先,HashMap中的数组长度决定了HashMap的存储容量,当数组中的元素个数超过数组长度的0.75倍(即负因子为0.75)时,HashMap会自动触发扩容操作。扩容操作会重新计算所有元素的哈希值,然后根据新的数组长度重新散列到新的数组中。 其次,当链表长度超过8时,HashMap会考虑将链表换为。这是因为链表的增删操作的时间复杂度为O(n),当链表长度过长时,查找效率会变低。而可以保证查找、插入和删除操作的时间复杂度都为O(log n),效率更高。 为了平衡存储容量和查询效率之间的关系,HashMap设置了一个阈值,即当数组长度大于等于64时,才会将链表换为。这是因为当数组长度过小时,哈希冲突的概率较低,使用链表存储即可满足查询效率的要求。但当数组长度变大时,哈希冲突的概率会增,此时将链表换为能够更好地提高查询效率。 综上所述,HashMap中的数组长度为64才能触发链表换为的条件,是为了在满足存储容量和查询效率的前提下,平衡哈希冲突的概率和查询操作的效率。 ### 回答3: 在HashMap中,数组长度决定了HashMap的容量。HashMap使用数组和链表的结合来实现数据存储和高效的查找。当HashMap的元素较少时,直接使用数组来存储元素是最高效的,而当元素增多时,就需要进行优化。 数组长度为64之所以被选为阈值,是因为这个值经过了大量的实验和研究得出的最优值。在这个长度数组中,每个数组位置上的链表平均长度为8时,哈希查找和插入操作均能在O(1)的时间复杂度内完成。 当链表长度超过8时,为了维持HashMap的高效性能,就需要将链表化为是一种自平衡的二叉搜索,它能够保证在最坏情况下,查找、插入和删除操作的时间复杂度为O(log n)。通过将链表换为,可以大大提升在大容量HashMap中的操作效率。 为什么数组长度为64才换为?这是因为在链表长度较小时,的数据结构相对于链表来说,具有更大的存储开销。只有当链表长度超过一定阈值时,将链表换为才能带来性能上的提升。而64作为阈值的选取,可以在大多数情况下平衡存储开销和性能之间的关系。 总而言之,当HashMap中的链表长度超过8时,为了保持操作的高效性能,会选择将链表换为数组长度为64是经验值,在这个长度数组中进行换,可以在大容量HashMap中取得较好的性能表现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值