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. A1121. Damn Single

    "Damn Single (单身狗)" is the Chinese nickname for someone who is being single. You are suppo ...

  2. 【洛谷 P2430 严酷的训练】

    题目背景 Lj的朋友WKY是一名神奇的少年,在同龄人之中有着极高的地位... 题目描述 他的老师老王对他的程序水平赞叹不已,于是下决心培养这名小子. 老王的训练方式很奇怪,他会一口气让WKY做很多道题 ...

  3. 第一篇-ubuntu18.04访问共享文件夹

    1. 在访问Windows共享资料之前,请确保Windows共享是可用的.Linux访问Windows共享或者LInux共享资料给Windows时,都使用Samba软件 rpm -qa | grep ...

  4. DAY1初识Python----变量及命名规则,注释,数据类型,常量,交互

     1.认识和了解python  python是一门解释型语言,弱类型语言 2.python发展史   2008年 2.X,3.X 3.第一个python程序  python语句可以写在命令行中,进行编 ...

  5. tensorflow-gpu版本出现libcublas.so.8.0:cannot open shared object file

    文章主要参考以下博客https://www.aliyun.com/zixun/wenji/1289957.html 在利用GPU加速tensorflow时,出现了libcublas.so.8.0:ca ...

  6. Vue(基础七)_webpack使用工具(下)

    一.前言  1.webpack.config文件配置                                          2.webpack打包css文件                 ...

  7. 使用PreparedStatement 查询一条数据 封装成一个学生的Student1对象

    package cn.lijun.entity; public class Student1 { private int id; private String sname; private int g ...

  8. Qt: 文件、文件夹的操作;

    Qt没有提供单独的函数来对文件.文件夹进行操作, 但是提供了两个类: QFile, QDir; 1.文件操作 ) 文件是否存在: QFile file("D:/test.jpg") ...

  9. qml: QtChart横纵轴label设置;

    在qml中,使用ChartView作为图表展示区域, 但是并没有给定接口用来设置xlabel,ylabel. 没得办法,只能采用笨方案: (我的方法如下) import QtQuick 2.0 imp ...

  10. qml: 支持的基本类型

    qml支持的基本类型有: bool unsigned int, int; float    double   qreal QString QUrl QColor QData,  QTime  QDat ...