关于hashMap中 计算hashCode的逻辑推理(二)
hashMap中,为了使元素在数组中尽量均匀的分布,所以使用取模的算法来决定元素的位置.如下:
//方法一:
static final int hash(Object key){//jdk1.8
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
//方法二:
static int indexFor(int h,int length){//低版本的源码
return h & (length - 1);//第三步,取模运算
}
方法一是我当前使用jdk版本的源码,
方法二是在网上查到的低版本的源码,
首先确认:当length总是2的n次方时, h & (length - 1) 等价于 hash对length取模 ,但是&比%具有更高的效率;(下文有对该方法的说明).
其次,方法一和方法二的原理是一样的,
在JDK1.8的实现中,优化了高位运算的算法,通过hashCode()的高16位异或低16位实现的:(h = k.hashCode()) ^ (h >>> 16),
主要是从速度、功效、质量来考虑的,这么做可以在数组table的length比较小的时候,也能保证考虑到高低Bit都参与到Hash的计算中,同时不会有太大的开销。
-----------------------------------
另开头:
为什么数组大小为2的幂时hashmap访问性能最高?
我在网上查了一些博文,好多都”举例说明“,来以事实说话,
其实我感觉这有取巧的嫌疑,
以下为我个人理解(错误的理解,文章结尾处已写明):
为什么取length(奇数)-1? 而不是 length(偶数)-1?
在进行&(逻辑与)运算时(例:a & b),只有当 a =true and b =true 时,结果才是 1,否则都是0;
所以,当 hash & 偶数 时, 二进制结果 就总会是偶数,这就导致 数组的偶数位被浪费,数组的奇数位的冲突概率 增高.
基于以上,所以 存储位置index = h & (length - 1); 中length取偶数 使得 hashMap具有更高的性能.
至于为什么选择 为2的幂? 接触尚短,我暂时还没想到,待后续.
-----------------------------------------------------------------------------------------
通过研读前辈们的博文,以下 为 为什么使用 2的幂 作为数组长度:
当容量一是为2的幂 时,h&(length - 1) == h%length,它俩是等价不等效的.!!!!!!!!
-------------------------
推导:
2^n转换成二进制就是1+n个0,减1之后就是0+n个1, 如16 -> 10000,15 -> 01111,那根据&位运算规则,都为1时,才为1,那0≤运算后的结果≤15,
假设h <= 15,那么运算后的结果就是h本身,h >15,运算后的结果就是最后三位二进制做&运算后的值,最终,就是%运算后的余数.
补充:
通过位运算(不用模运算符%)求余
前提:a/b的除数 b必须为2的 你次方.也就是说b必须是
2的一次方 1
2的二次方 4
2的三次方 8
......
......
只有是这样的一种情况,这种方法才是正确的.
如下两种方法:
方法一:a%b = a&( b -1);
例:
a=9 , b= 8. 小括号内的值为b-1 = 8-1 =7. 9 的二进制表现:1001,7的二进制表现:0111, a%b = a&(b-1) = 9%8 = 9&(8-1) 的结果值:0001 = 1.也就是说,余数为1.结果是正确的.
方法二:a%b = a-((a>>log2[b])<<log2[b]);
例:
初始值还是 a= 9,b = 8. a-((a>>3)<<3) 先右移3位,再左移三维,然后a减去移位后的值.
在hashMap中使用的方法一.
因此,容量(数组长度)必须为2的幂方.
上文中我自己的想法也是不对的. 长度取偶数 那只是取2的幂方的 结果属性.并不是原因之一.上文就不删改了, 留下个记号完整学习过程.
关于hashMap中 计算hashCode的逻辑推理(二)的更多相关文章
- hashCode及HashMap中的hash()函数
一.hashcode是什么 要理解hashcode首先要理解hash表这个概念 1. 哈希表 hash表也称散列表(Hash table),是根据关键码值(Key value)而直接进行访问的数据结构 ...
- [ 转载 ]hashCode及HashMap中的hash()函数
hashCode及HashMap中的hash()函数 一.hashcode是什么 要理解hashcode首先要理解hash表这个概念 1. 哈希表 hash表也称散列表(Hash table),是 ...
- HashMap中使用自定义类作为Key时,为何要重写HashCode和Equals方法
之前一直不是很理解为什么要重写HashCode和Equals方法,才只能作为键值存储在HashMap中.通过下文,可以一探究竟. 首先,如果我们直接用以下的Person类作为键,存入HashMap中, ...
- Java中hashCode()方法以及HashMap()中hash()方法
Java的Object类中有一个hashCode()方法: public final native Class<?> getClass(); public native int hashC ...
- java中equals和hashCode方法随笔二
前几天看了篇关于java中equals和hashCode方法的解析 1.Object类中的equals方法和hashCode方法. Object类中的equals和hashCode方法简单明了,所有的 ...
- 千万不要误用 java 中的 HashCode 方法
刚才debug追堆栈的时候发现一个很奇怪的问题 我用IE8和Google的浏览器访问同一个地址 Action的 scope="session" 也设置了 而且两个浏览器提交的参数m ...
- java中的hashcode方法作用以及内存泄漏问题
本文装载:http://hi.baidu.com/iduany/item/6d66dfc9d5f2da1650505870 hashCode()方法的作用&使用分析 一直以来都想写篇文章来说明 ...
- HashMap中的散列函数、冲突解决机制和rehash
一.概述 散列算法有两个主要的实现方式:开散列和闭散列,HashMap采用开散列实现. HashMap中,键值对(key-value)在内部是以Entry(HashMap中的静态内部类)实例的方式存储 ...
- Java中的hashCode() 和 equals()的若干问题解答
一.hashCode()的作用 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int ...
随机推荐
- 用Python计算幂的两种方法,非递归和递归法
用Python计算幂的两种方法: #coding:utf-8 #计算幂的两种方法.py #1.常规方法利用函数 #不使用递归计算幂的方法 """ def power(x, ...
- bzoj1218 激光炸弹
bz上难得一见的水题啊. 我们发现:这个SB居然只要枚举就行了!!! 我TM...... /****************************************************** ...
- 【洛谷P3275】糖果
题目大意:维护 M 个差分约束关系,问是否可以满足所有约束,如果满足输出一组解.\(N<=1e5\) 题解:差分约束模型可以通过构建一张有向图来求解.是否满足所有约束可以利用 spfa 进行判断 ...
- django2用模板代码图标字体丢失报404 cJZKeOuBrn4kERxqtaUH3T8E0i7KZn-EPnyo3HZu7kw.woff
以前开发网站,不是用php就是用c#或java写后端,跟后端繁重麻烦的代码相比,前端的html+css+JavaScript简直就简单的不算技术,相比之下,工作量也不大. 但如果用django框架,使 ...
- python3+django2 开发易语言网络验证(下)
第六步:网络验证服务器端项目上线部署 功夫不负有心人,终于部署成功啦! 前期准备: 项目名:netauth 系统:百度云服务器下的Ubuntu16.4 软件:xshell(无论如何想办法用这个跟服务器 ...
- 斯坦福大学公开课机器学习: machine learning system design | prioritizing what to work on : spam classification example(设计复杂机器学习系统的主要问题及构建复杂的机器学习系统的建议)
当我们在进行机器学习时着重要考虑什么问题.以垃圾邮件分类为例子.假如你想建立一个垃圾邮件分类器,看这些垃圾邮件与非垃圾邮件的例子.左边这封邮件想向你推销东西.注意这封垃圾邮件有意的拼错一些单词,就像M ...
- 动态代理之: com.sun.proxy.$Proxy0 cannot be cast to 问题
转: 动态代理之: com.sun.proxy.$Proxy0 cannot be cast to 问题 2018年05月13日 00:40:32 codingCoge 阅读数:1211 版权声明 ...
- Day036--Python--线程
1. 线程 from threading import Thread def func(n): print(n) if __name__ == '__main__': t = Thread(targe ...
- postman 请求带cookie
以亚马逊为例,我抓包随便看一个返回是json数据格式的一个接口,比如随便点一个,我的订单 随便找一条,然后复制url过滤 右键,copy下url 将url放入filter过滤: 在postman里面, ...
- typedef typename的用法
我自己最后在这篇文章里理解:[C++]typedef typename什么意思? typedef typename A::a_type b_type; 其中typename是告诉编译器A::a_typ ...