HashMap之HashMap中hashSeed(hash种子)的作用分析

1.扩容时需要调用transfer()进行节点的转移,此时传入第二个参数是是否需要rehash的boolean类型,即初始化hash种子

void resize(int newCapacity) {Entry[] oldTable = table;int oldCapacity = oldTable.length;if (oldCapacity == MAXIMUM_CAPACITY) {threshold = Integer.MAX_VALUE;return;}Entry[] newTable = new Entry[newCapacity];transfer(newTable, initHashSeedAsNeeded(newCapacity));table = newTable;threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
}

2.代码分析:

(1)首先hashSeed默认是0,currentAltHashing为false,sun.misc.VM.isBooted()判断jvm是否启动,开始运行为true

(2)只要(capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD)为true,useAltHashing就为true

(3)如果useAltHashing为true,因为currentAltHashing为false,且^(相同为0,不同为1),那么switching就为true

(4)如果switching为true,那么useAltHashing为true,那就可以给hashseed进行重新赋值,sun.misc.Hashing.randomHashSeed(this),

(5)所以根源在于第二步capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD是否为true,

ALTERNATIVE_HASHING_THRESHOLD = threshold;
threshold = (null != altThreshold)? Integer.parseInt(altThreshold): ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;
String altThreshold = java.security.AccessController.doPrivileged(new sun.security.action.GetPropertyAction("jdk.map.althashing.threshold"));
static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;

(6)可以看到ALTERNATIVE_HASHING_THRESHOLD值为多少最终取决于altThreshold是否为null,而这个值我们又可以通过java虚拟机参数-D jdk.map.althashing.threshold=xxx进行配置,如果没有配置,默认为null,如果配置了,altThreshold就为我们配置的值,

(7)所以结论就是:如果我们配置了jdk.map.althashing.threshold值,Holder.ALTERNATIVE_HASHING_THRESHOLD就为我们配置的值,如果没有配置就为Integer.MAX_VALUE,

那么也就是说:因为数组容量不可能达到Integer.MAX_VALUE,如果没有配置capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD就为false,switching也为false,也就不需要rehash,如果配置了,一旦capacity达到了我们配置的值,switching为true,就需要重新计算一个hashseed的值,并且rehash

final boolean initHashSeedAsNeeded(int capacity) {boolean currentAltHashing = hashSeed != 0;boolean useAltHashing = sun.misc.VM.isBooted() &&(capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);boolean switching = currentAltHashing ^ useAltHashing;if (switching) {hashSeed = useAltHashing? sun.misc.Hashing.randomHashSeed(this): 0;}return switching;
}

3.如果rehash为true,也就是需要rehash,那么就需要重新计算hash值,调用hash()

void transfer(Entry[] newTable, boolean rehash) {int newCapacity = newTable.length;for (Entry<K,V> e : table) {while(null != e) {Entry<K,V> next = e.next;if (rehash) {e.hash = null == e.key ? 0 : hash(e.key);}int i = indexFor(e.hash, newCapacity);e.next = newTable[i];newTable[i] = e;e = next;}}
}

4.如果一旦调用了rehash()方法,那么hashseed一定也被重新赋值了,我们就需要跟据其他算法,再次计算一下hash()值

final int hash(Object k) {int h = hashSeed;if (0 != h && k instanceof String) {return sun.misc.Hashing.stringHash32((String) k);}h ^= k.hashCode();// This function ensures that hashCodes that differ only by// constant multiples at each bit position have a bounded// number of collisions (approximately 8 at default load factor).h ^= (h >>> 20) ^ (h >>> 12);return h ^ (h >>> 7) ^ (h >>> 4);
}
总结:使用hash种子的目的就是:用hashseed决定获取hash值的方式,如果一旦数组容量超过了我们自己配置的值,就会生成新的hash种子,不再通过异或方式获取hash值,而是通过调用sun.misc.Hashing.stringHash32()方法,获取hash值,从而提高hash值的散列性,减小hash碰撞的产生,缩短了链表的长度,提高了效率。

视频链接:https://www.bilibili.com/video/BV1x741117jq?p=3&spm_id_from=333.1007.top_right_bar_window_history.content.click

HashMap之HashMap中hashSeed(hash种子)的作用分析相关推荐

  1. HashMap和Hashtable中的hash值是怎么计算的

    上一篇讲了String.Integer复写了Object中的hashCode方法,而对于HashMap或类对象来说是直接使用了Object中的hashCode方法.正文如下: public class ...

  2. 全网把Map中的hash()分析的最透彻的文章,别无二家。

    你知道HashMap中hash方法的具体实现吗?你知道HashTable.ConcurrentHashMap中hash方法的实现以及原因吗?你知道为什么要这么实现吗?你知道为什么JDK 7和JDK 8 ...

  3. bat从数组中找出相同数字并删除_全网把Map中的hash()分析的最透彻的文章,别无二家...

    原文地址:https://mp.weixin.qq.com/s/qCHkzs4JPOipB-ZzqrfbeQ 作者: Hollis 你知道HashMap中hash方法的具体实现吗? 你知道HashTa ...

  4. HashMap中的hash函数

    在写一个HashSet时候有个需求,是判断HashSet中是否已经存在对象,存在则取出,不存在则add添加.HashSet也是通过HashMap实现,只用了HashMap的key,value都存储一个 ...

  5. HashMap中的hash与rehash

    HashMap中的hash与rehash 我们知道HashMap中经常用到hash()方法. 比如:put()方法中 public V put(K key, V value){if(key==null ...

  6. HashMap中的Hash码怎么计算,为什么要这样做?

    HashMap面试系列(1) Q:HashMap中的Hash码如何计算?为什么要这么做? 注意:HashCode()是对象的Hash码,和HashMap中的Hash码不是同一个东西 1.8版本如下 s ...

  7. 盘点 HashMap 源码中的那些优雅的设计!

    以下文章来源方志朋的博客,回复"666"获面试宝典 一.HashMap构造器 HashMap总共给我们提供了三个构造器来创建HashMap对象. 1.无参构造函数public Ha ...

  8. HashMap的实现原理及hash冲突(碰撞)解决方法

    HashMap 采用一种所谓的"Hash 算法"来决定每个元素的存储位置.当程序执行 map.put(String,Obect)方法 时,系统将调用String的 hashCode ...

  9. HashMap/HashMap存储/HashMap扩容

    HashMap Java 集合,也称作容器,主要是由两大接口 (Interface)派生出来的:Collection 和 Map. Map集合体系: Map集合特点: (1) 键值对存储(key-va ...

  10. 【集合之HashMap】HashMap实现原理及非线程安全原因

    要知道HashMap是什么,首先要搞清楚它的数据结构,在Java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也 ...

最新文章

  1. 2021年大数据Hadoop(十):HDFS的数据读写流程
  2. mysql数据库会同时执行sql吗_mysql 一次执行多条sql语句
  3. 线性规划的原始对偶算法
  4. php扩展 静态库,编译PHP扩展的方法
  5. JavaScript对象理解
  6. WebSphere MQ----通道
  7. iPhone音频播放后台控制
  8. ISA2006的部署
  9. Oracle学习:序列
  10. java流与文件——操作文件
  11. mysql安装使用--2 用户管理
  12. python邮箱爆破_Python在线爆破邮箱账号密码测试代码(亲测可用)
  13. weblogic部署,常见错误解决二——ClassCastException
  14. 在EI中查找某作者的会议论文是否被收录
  15. msdb 数据库_如何检索有关存储在MSDB数据库中的SSIS包的信息
  16. 【IT项目管理】第5章 保障项目进度
  17. java实现26个大写字母的遍历
  18. 小刘同学的第七十四篇博文
  19. 骑士游历问题【JAVA板】代码详细流
  20. Metasploitable2虚拟机镜像下载地址

热门文章

  1. 软考数据库系统工程师是什么?如何备考?
  2. 已知圆上三个点坐标,求圆半径 r 和 圆心坐标
  3. JAVA-反射面试题及答案
  4. Java开发揭秘!java反射和映射机制
  5. Java导出Excel数据错乱
  6. 使用站长工具进行目标域名登记查询
  7. 走进小作坊(十五)----疯狂的站长
  8. 特大喜讯!鸿蒙项目来了:在线电子词典
  9. 基于JAVA影院网上售票系统演示录像计算机毕业设计源码+系统+数据库+lw文档+部署
  10. 关于代理服务器与NAT