HashMap的长度为什么要是2的n次方
HashMap为了存取高效,要尽量较少碰撞,就是要尽量把数据分配均匀,每个链表长度大致相同,这个实现就在把数据存到哪个链表中的算法;
这个算法实际就是取模,hash%length,计算机中直接求余效率不如位移运算,源码中做了优化hash&(length-1),
hash%length==hash&(length-1)的前提是length是2的n次方;
为什么这样能均匀分布减少碰撞呢?2的n次方实际就是1后面n个0,2的n次方-1 实际就是n个1;
例如长度为9时候,3&(9-1)=0 2&(9-1)=0 ,都在0上,碰撞了;
例如长度为8时候,3&(8-1)=3 2&(8-1)=2 ,不同位置上,不碰撞;
其实就是按位“与”的时候,每一位都能 &1 ,也就是和1111……1111111进行与运算
0000 0011 3
& 0000 1000 8
= 0000 0000 0
0000 0010 2
& 0000 1000 8
= 0000 0000 0
-------------------------------------------------------------
0000 0011 3
& 0000 0111 7
= 0000 0011 3
0000 0010 2
& 0000 0111 7
= 0000 0010 2
当然如果不考虑效率直接求余即可(就不需要要求长度必须是2的n次方了);
有人怀疑两种运算效率差别到底有多少,我做个测试:
/**
*
* 直接【求余】和【按位】运算的差别验证
*/
public static void main(String[] args) { long currentTimeMillis = System.currentTimeMillis();
int a=0;
int times = 10000*10000;
for (long i = 0; i < times; i++) {
a=9999%1024;
}
long currentTimeMillis2 = System.currentTimeMillis(); int b=0;
for (long i = 0; i < times; i++) {
b=9999&(1024-1);
} long currentTimeMillis3 = System.currentTimeMillis();
System.out.println(a+","+b);
System.out.println("%: "+(currentTimeMillis2-currentTimeMillis));
System.out.println("&: "+(currentTimeMillis3-currentTimeMillis2));
}
结果:
783,783
%: 359
&: 93
---------------------
本文来自 四滴火 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/sidihuo/article/details/78489820?utm_source=copy
HashMap的长度为什么要是2的n次方的更多相关文章
- 【Java集合】为什么HashMap的长度是2的N次幂?
这个问题应该倒过来思考,HashMap的长度是2的N次幂,有什么优势? 在HashMap的putVal()方法中,为了确定插入元素在table[]数组中的下标位置,使用的与(&)运算来计算 如 ...
- HashMap的最大容量为什么是2的30次方?
今天看HashMap的底层实现,发现HashMap的最大容量规定为: // 最大容量(必须是2的幂且小于2的30次方,传入容量过大将被这个值替换) static final int MAXIMUM_C ...
- hashmap 为什么初始化容量是2的幂次方
个人理解 做下记录,不正确的地方望不吝赐教 这是hashmap初始化容量时候 对容量大小做的处理,保证初始化容量为最近的2的幂次方(JDK1.8) static final int tableSize ...
- Android版数据结构与算法(四):基于哈希表实现HashMap核心源码彻底分析
版权声明:本文出自汪磊的博客,未经作者允许禁止转载. 存储键值对我们首先想到HashMap,它的底层基于哈希表,采用数组存储数据,使用链表来解决哈希碰撞,它是线程不安全的,并且存储的key只能有一个为 ...
- HashMap与ConcurrentHashMap、HashTable
(1)HashMap的线程不安全原因一:死循环 原因在于HashMap在多线程情况下,执行resize()进行扩容时容易造成死循环. 扩容思路为它要创建一个大小为原来两倍的数组,保证新的容量仍为2的N ...
- HashMap、Hash Table、ConcurrentHashMap
这个这个...本王最近由于开始找实习工作了,所以就在牛客网上刷一些公司的面试题,大多都是一些java,前端HTML,js,jquery,以及一些好久没有碰的算法题,说实话,有点难受,其实在我不知道的很 ...
- HashMap了解吗?
HashCode() HashMap 底层实现 HashMap 的长度为什么默认初始长度是16,并且每次resize()的时候,长度必须是2的幂次方? HashMap 死链问题 Java 8 与 Ja ...
- [转帖]HashMap、HashTable、ConcurrentHashMap的原理与区别
HashMap.HashTable.ConcurrentHashMap的原理与区别 http://www.yuanrengu.com/index.php/2017-01-17.html 2017年1月 ...
- Java中HashMap扩容机制思考
1. HashMap在什么条件下扩容 判断HashMap的数组Size大小如果超过loadFactor*capacity,就要扩容. 相关的类属性: capacity:当前数组容量,始终保持 2^n, ...
随机推荐
- jquery 取子节点及当前节点属性值
分享下jquery取子节点及当前节点属性值的方法. <li class="menulink"><a href="#" rel="ex ...
- Android Shell命令dumpsys
dumpsys命令可以显示手机中所有应用程序的信息,并且也会给出现在手机的状态. 直接执行adb shell dumpsys KEY 会显示以下所有信息. KEY的可选名称 SurfaceFlinge ...
- 50x页面放到本地单独目录下,进行显示
error_page 500 502 503 504 /50x.html; location = /50x.html { root /data0/www/html; }
- step-by-step-creating-a-sql-server-2012-alwayson-availability-group/
https://blogs.technet.microsoft.com/canitpro/2013/08/19/step-by-step-creating-a-sql-server-2012-alwa ...
- iOS进阶指南试读之UI篇
iOS进阶指南试读之UI篇 UI篇 UI是一个iOS开发工程师的基本功.怎么说?UI本质上就是你调用苹果提供给你的API来完成设计师的设计.所以,想提升UI的功力也很简单,没事就看看UIKit里的各个 ...
- DLL中获取主程序句柄
一.问题由来及说明 在实际编程中遇到一些系统模块(或API)调用初始化需要窗口句柄,在主程序中(MFC或者win32)都可以很容易获得,比如mfc中可以直接调用AfxGetMainWnd().GetS ...
- Python3机器学习—Tensorflow数字识别实践
[本文出自天外归云的博客园] Windows下Anaconda+Tensorflow环境部署 1. 安装Anaconda. 2. 开始菜单 > 所有程序 > Anaconda 3 (64- ...
- rapidjson使用总结
Reference: https://blog.csdn.net/elloop/article/details/49908689 rapidjson简介 rapidjson是腾讯的开源json解析框 ...
- linux磁盘 分区 物理卷 卷组 逻辑卷 文件系统加载点操作案例
转自:truemylife.linux磁盘 分区 物理卷 卷组 逻辑卷 文件系统加载点操作案例 基本概念: 磁盘.分区.物理卷[物理部分] 卷组[中间部分] 逻辑卷.文件系统[虚拟化后可控制部分] 磁 ...
- JAVA-JSP内置对象之request获得所有的参数名称
相关资料:<21天学通Java Web开发> 获得所有的参数名称1.request对象的getParameterNames()方法可以获得所有的参数名称. RequestForm2.jsp ...