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的逻辑推理(二)的更多相关文章

  1. hashCode及HashMap中的hash()函数

    一.hashcode是什么 要理解hashcode首先要理解hash表这个概念 1. 哈希表 hash表也称散列表(Hash table),是根据关键码值(Key value)而直接进行访问的数据结构 ...

  2. [ 转载 ]hashCode及HashMap中的hash()函数

    hashCode及HashMap中的hash()函数   一.hashcode是什么 要理解hashcode首先要理解hash表这个概念 1. 哈希表 hash表也称散列表(Hash table),是 ...

  3. HashMap中使用自定义类作为Key时,为何要重写HashCode和Equals方法

    之前一直不是很理解为什么要重写HashCode和Equals方法,才只能作为键值存储在HashMap中.通过下文,可以一探究竟. 首先,如果我们直接用以下的Person类作为键,存入HashMap中, ...

  4. Java中hashCode()方法以及HashMap()中hash()方法

    Java的Object类中有一个hashCode()方法: public final native Class<?> getClass(); public native int hashC ...

  5. java中equals和hashCode方法随笔二

    前几天看了篇关于java中equals和hashCode方法的解析 1.Object类中的equals方法和hashCode方法. Object类中的equals和hashCode方法简单明了,所有的 ...

  6. 千万不要误用 java 中的 HashCode 方法

    刚才debug追堆栈的时候发现一个很奇怪的问题 我用IE8和Google的浏览器访问同一个地址 Action的 scope="session" 也设置了 而且两个浏览器提交的参数m ...

  7. java中的hashcode方法作用以及内存泄漏问题

    本文装载:http://hi.baidu.com/iduany/item/6d66dfc9d5f2da1650505870 hashCode()方法的作用&使用分析 一直以来都想写篇文章来说明 ...

  8. HashMap中的散列函数、冲突解决机制和rehash

    一.概述 散列算法有两个主要的实现方式:开散列和闭散列,HashMap采用开散列实现. HashMap中,键值对(key-value)在内部是以Entry(HashMap中的静态内部类)实例的方式存储 ...

  9. Java中的hashCode() 和 equals()的若干问题解答

    一.hashCode()的作用 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int ...

随机推荐

  1. 【git】git一些命令使用记录

    目前git版本控制很多公司都在用,我把平时的使用做些记录,防止忘记. 1. 有时候分支比较多,我们会基于master建立一个新分支开发,有时候也会基于别的分支建立,但时间长了可能会忘记当前分支是基于哪 ...

  2. A/D和D/A的学习

    从我们学到的知识了解到,我们的单片机是一个典型的数字系统.数字系统只能对输入的数字信号进行处理,其输出信号也是数字信号.但是在工业检测系统和日常生活中的许多物理量都是模拟量,比如温度.长度.压力.速度 ...

  3. spring-boot-starter-redis配置详解

    spring-boot-starter-redis配置详解   spring-boot-starter-redis主要是通过配置RedisConnectionFactory中的相关参数去实现连接red ...

  4. Vim常用插件安装及配置方法

    Vundle 安装 git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim 配置 vimrc首部添 ...

  5. 洛谷P2178 品酒大会

    题意:若两个字符开始的后面r个字符都一样,则称这两个字符是r相似的.它们也是r-1相似的. 对于r∈[0,n)分别求有多少种方案,其中权值最大方案权值是多少.此处权值是选出的两个字符的权值之积. 解: ...

  6. 洛谷P4248 差异

    题意:求所有后缀两两之间的最长公共前缀的长度之和. 解:这道题让我发现了一个奇妙的性质:所有后缀两两最长公共前缀长度之和 和 所有前缀两两最长公共后缀之和的值是相等的,但是每一组公共前/后缀是不同的. ...

  7. 【洛谷P2142 高精度减法】

    题目描述 高精度减法 输入输出格式 输入格式: 两个整数a,b(第二个可能比第一个大) 输出格式: 结果(是负数要输出负号) 输入输出样例 输入样例#1: 复制 2 1 输出样例#1: 复制 1 说明 ...

  8. HTML学习笔记Day8

    一.设置元素背景透明属性{background:rgba(255,255,255,0.5):} 1.元素背景透明,内容正常显示: 注:opacity:value:元素背景透明内容也透明: 2.rgba ...

  9. Mac 上有哪些鲜为人知且极大提高效率的工具?

    来源:知乎文章收录于:风云社区SCOEE,提供上千款各类mac软件下载 1. Focus  功能: 屏蔽影响你学习的网站.  同类软件:Self Control, Rescue Time  特点 ...

  10. python自动化开发-[第九天]-异常处理、进程

    今日概要: 1.异常处理使用 2.进程 3.paramiko模块使用 一.异常处理 1.常见的错误异常 #错误异常一 print(a) #NameError #错误异常二 int('sdadsds') ...