HashMap 的长度为什么是2的幂次方

2024-08-24 04:44
文章标签 hashmap 次方 长度

本文主要是介绍HashMap 的长度为什么是2的幂次方,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

HashMap 的长度为什么是2的幂次方

因为这样可以让计算桶位置的操作更加高效。

具体来说,如果 HashMap 的长度是 2 的幂次方,那么计算桶位置时可以使用位运算来代替除法运算,从而提高计算速度。

我们都知道为了找到 KEY 的位置在哈希表的哪个槽里面,需要计算 hash(KEY) % 数组长度

HashMap为了存取高效,就要尽量减少碰撞,将数据分配均匀,那么如何分配均匀,此时主要靠将数据存入到那个链表中的算法,这个算法就是 hash(KEY) & (length - 1)。& 是按位与运算,是一个位运算,而在计算机中位运算的效率很高,% 计算比 & 慢很多,这就是不用%运算的原因,为了保证 & 的计算结果等于 % 的结果需要把 length 减 1。

hash(KEY) & (length - 1)=hash(KEY) %length

既然两个计算出的hash值是相同的那当然是用效率更高的&

我做了一个小实验:

假设现在数组的长度:2 ^ 14 = 16384

String key = "zZ1!." 的 hash 值为 115398910

public static void main(String[] args) {String key = "zZ1!.";System.out.println(key.hashCode());// 115398910
}

hash & (length - 1) = 115398910 & 16383 = 6398 (你可以使用电脑的计算机验证一下是不是对的)6398 的二进制是 ‭0001100011111110‬

hash % length = 115398910 % 16384 = 6398

这样可以大大提高计算速度,因为按位与运算比取模运算要快得多。

另外,长度为 2 的幂次方的数组也可以更好地处理哈希冲突。在使用链表解决哈希冲突时,如果数组长度是 2 的幂次方,那么每个桶的链表长度最多只有 8 个元素,这样可以保证链表的查找效率。如果数组长度不是 2 的幂次方,那么桶的数量可能不能均匀分布,从而导致某些桶的链表长度很长,影响查找效率。

因此,为了提高 HashMap 的性能,通常建议将长度设置为 2 的幂次方。

骚戴理解:如果数组长度是 2 的幂次方,每个桶的链表长度最多只有 8 个元素是因为 JDK 1.8 中 HashMap 的实现使用了一种称为“树化”的策略,当某个桶中的链表长度超过了 8 个元素时,会将该链表转换成红黑树,以提高查找效率。

树化操作的前提条件是桶中的链表长度超过了阈值(默认为 8),而如果数组长度是 2 的幂次方,那么对于任意的哈希值,它与数组长度的按位与操作的结果一定是小于数组长度的。例如,如果数组长度是 16,那么对于任意的哈希值,它与 15 的按位与操作的结果一定是在 0 到 15 之间。

因此,如果数组长度是 2 的幂次方,那么对于任意的哈希值,它与数组长度的按位与操作的结果一定是小于数组长度的,也就是说,它一定可以作为桶的下标。而由于数组长度是 2 的幂次方,因此桶的数量也是 2 的幂次方,这样就可以保证桶的数量和数组长度是一致的,从而可以保证每个桶的链表长度最多只有 8 个元素。

需要注意的是,这种情况只针对 JDK 1.8 中 HashMap 的实现,如果使用其他版本的 HashMap 或者其他哈希表实现,可能不具备这种性质。

那为什么是两次扰动呢?

答:这样就是加大哈希值低位的随机性,使得分布更均匀,从而提高对应数组存储下标位置的随机性&均匀性,最终减少Hash冲突,两次就够了,已经达到了高位低位同时参与运算的目的;

这篇关于HashMap 的长度为什么是2的幂次方的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1101478

相关文章

HashMap中常用的函数

假设如下HashMap<String, Integer> map = new HashMap<>();获取value值1、返回key为a的valueget(a)2、返回key为a的value,若没有该key返回0getOrDefault(a,0)新增键值对1、新增键值对(a,1)put(a,1)2、如果key为a的键不存在,则存入键值对(a,1)putIfAbsent(a,1)3

hashmap的存值,各种遍历方法

package com.jefflee;import java.util.HashMap;import java.util.Iterator;import java.util.Map;public class HashmapTest {// 遍历Hashmap的四种方法public static void main(String[] args) {//hashmap可以存一个null,把

Java应用对接pinpoint监控工具的时候,应用名称长度超出限制而导致接入失败

一、背景 java应用需要接入pinpoint,同一个虚拟机上的其他应用接入成功,唯独本应用不行。 首先排除是pinpoint agent的问题,因为其他应用都正常。 然后,我就对比二者的启动脚本。 -javaagent:/opt/pinpoint/pinpoint-bootstrap.jar -Dpinpoint.agentId=DA301004_17 -Dpinpoint.applic

2300年都无人能知有长度不同的伪≌射线

黄小宁 【摘要】自有射线概念后的2300年里一直无人能知有长度不同的射线。保距变换和≌图概念是能放大无穷大倍的思维望远镜使人能一下子看到有长度不同的伪重合、伪≌射线。 变量x所取各数也均由x代表,x代表其变域(x所有能取的数组成的集)内任一元。设集A={x}表A各元均由x代表,{x}中变量x的变域是A。其余类推。“实数集”R所有非负元x≥0组成R+={x≥0},这里的x≥0不是表示x可取一切非负

MQTT协议中信息长度MSG len字段分析

截图自: 主要是说数据字节长度的计算: 每个字节由1个持续位和7个数据位组成:如果持续位为1,表示接下来的一个字节仍然表示长度的一部分 7个数据位表示的数据     0-127   共计128个数字 所以如上图的表格所示 1个字节,2个字节,3个字节,4个字节的数据范围 切记:MQTT长度的表示范围 最多使用4个字节  故这里存在着数据长度的限制  (不过真心牛掰! 试试Q

EL表达式获取List集合长度

有一次在jsp页面我要获取后台的一个list集合的长度,当然你可以在后台保存长度然后在页面获取,这是一种方法,现在我介绍另一种方法: 首先:我们在jsp页面导入jstl标签库<%@ taglib prefix="fn" uri="http://java.sun.com/jsp.jstl/functions"%> 然后在你要获取的地方写上:${fn:length(qunarRemarkList)

容器第五课,Map和HashMap的基本用法,hashMap和HashTable的区别

Map接口 实现Map接口的类用来存储键(Key) --- 值(value)对。 Map接口的实现类有HashMap和TreeMap类 Map类中存储的键---值对通过键来标识,所以键值不能重复 package com.pkushutong.Collection;import java.util.HashMap;import java.util.Map;/*** 测试Map的基本用法

面试:HashMap

文章引用: http://www.importnew.com/7099.html https://blog.csdn.net/niuwei22007/article/details/52005329 HashMap的工作原理是近年来常见的Java面试题。几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hashtable和HashMap之间的区别,那么

HashMap 源码分析(删除+总结)JDK1.8

文章来源: 1 https://segmentfault.com/a/1190000012926722#articleHeader7 2 https://www.zhihu.com/question/20733617 3 https://tech.meituan.com/java-hashmap.html 4 https://www.zhihu.com/question/5752

mysql数据库中的字符串长度函数:LENGTH() 与 CHAR_LENGTH()

在数据库管理系统中,处理字符串数据时,了解字符串的长度是一个常见且重要的需求。无论是为了数据验证、格式化输出,还是在进行复杂的查询操作中,准确获取字符串的长度都是必不可少的。SQL标准提供了几种函数来帮助我们实现这一目标,其中LENGTH()和CHAR_LENGTH()是两个常被提及的函数,尽管它们在某些数据库系统中可能表现出相似的行为,但在一些细节上存在差异。本文将深入探讨这两个函数的用法及其区