关于HashMap中的扰动函数的疑问
最近再看jdk8的hashmap源码,当看到这一步的时候有点疑问,去网上搜了一下,看到的所有文章基本上都是一篇抄一篇的(反正目前各大社区就是这么个状况),那个意思就是让高16位也参与运算,增加结果的随机性,减小hash碰撞???
乍一听好像是那么回事,但是越想越不对劲;我怎么都觉得是无论怎么运算最后不都是看低几位吗,在哪个固定的长度里每个数出现的概率不还是随机的吗(1/length);高位参与运算之后肯定能保证的是原来低位相同的值更加不同,但是不能保证本来不同的值运算后还是不通吧。怀着各种疑问,简单做了下实验。
与运算基数从2的4次幂到16次幂,分别对原始hash和扰动函数后的值进行统计
实验数据为随机8为的字符串值,平时我们用字符串作为key的情况最多吧
最后统计结果为:100次碰撞率的均值
代码:
import com.alibaba.fastjson.JSON; import java.util.ArrayList;
import java.util.Random;
import java.util.List; /**
* @description:
* @author: wukong
* @remark: create wukong 2019/12/26 22:49
*/
public class HashTest {
public static void main(String[] args) {
int length = 1 << 8;
List<Double> doubles = new ArrayList<>(100);
List<Double> double2s = new ArrayList<>(100);
// 测试次数
int count = 100;
for (int i = 0; i < count; i++) {
hashCalculate(length, doubles, double2s);
}
System.out.println("均值1:" + doubles.stream().mapToDouble((item) -> item).summaryStatistics().getAverage());
System.out.println("均值2:" + double2s.stream().mapToDouble((item) -> item).summaryStatistics().getAverage());
System.out.println("集合1:" + JSON.toJSON(doubles));
System.out.println("集合2" + JSON.toJSON(double2s));
} /**
* @Description: hash碰撞率计算
*/
private static void hashCalculate(int length, List<Double> doubles, List<Double> double2s) {
int cardinal = length - 1;
int load = (int) (length * 0.75);
int crash = 0;
int crash2 = 0;
List<Integer> list = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
for (int i = 0; i < load; i++) {
// 随机key获取哈希值
int hash = getRandomString().hashCode();
// 直接与基数进行与运算
int result = cardinal & hash;
// jdk8中hashmap扰动函数
int disturbHash = hash ^ (hash >>> 16);
// 扰动后的值与运算
int result2 = cardinal & disturbHash;
//统计直接运算碰撞次数
if (!list.contains(result)) {
list.add(result);
} else {
crash++;
}
//统计扰乱后碰撞次数
if (!list2.contains(result2)) {
list2.add(result2);
} else {
crash2++;
}
}
double crashProbability = crash / (double) length;
double crashProbability2 = crash2 / (double) length;
doubles.add(crashProbability);
double2s.add(crashProbability2);
// System.out.println("当长度为" + length + "时,hash值直接与运算的碰撞率为:" + crashProbability);
// System.out.println("当长度为" + length + "时,扰动函数之后与运算的碰撞率为:" + crashProbability2);
} /**
* @Description: 获取随机key字符串
*/
private static String getRandomString() {
String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
int length = 8;
for (int i = 0; i < length; i++) {
int number = random.nextInt(62);
sb.append(str.charAt(number));
}
return sb.toString();
}
}
运行结果示例(以下长度为2的16次幂时):
将数据整理完成后,做了一个折线图:
根据实验结果,我得到结论和我的想法一致,两者碰撞率应该会趋于一致,这个扰动函数好像是没用的,更确切的说这一步所有的扰动函数应该都是没用的。。。。。
我做完实验后,不知道是喜是悲,人家设计的怎么会有问题,还有更多的人也认同那样的设计,但是我却越想越觉得这一步是不可能降低碰撞率的。。。。也不知是我哪里想偏了,想错了,还是因为概率论什么的没学,或者是实验的时候哪里写错了,希望各位能纠正一下我错误的想法
关于HashMap中的扰动函数的疑问的更多相关文章
- HashMap中的hash算法中的几个疑问
HashMap中哈希算法的关键代码 //重新计算哈希值 static final int hash(Object key) { int h; return (key == null) ? 0 : (h ...
- HashMap中的hash函数
在写一个HashSet时候有个需求,是判断HashSet中是否已经存在对象,存在则取出,不存在则add添加.HashSet也是通过HashMap实现,只用了HashMap的key,value都存储一个 ...
- HashMap中的hash算法总结
前言 算法一直是我的弱项,然而面试中基本是必考的项目,刚好上次看到一个HashMap的面试题,今天也来学习下 HashMap中的hash算法是如何实现的. 数学知识回顾 << : 左移运算 ...
- 关于HashMap中hash()函数的思考
关于HashMap中hash()函数的思考 JDK7中hash函数的实现 static int hash(int h) { h ^= (h >>> 20) ^ (h >&g ...
- 如果两个对象具有相同的哈希码,但是不相等的,它们可以在HashMap中同时存在吗?
如果两个对象具有相同的哈希码,但是不相等的,它们可以在HashMap中同时存在吗? ----答案是 可以 原因: 在hashmap中,由于key是不可以重复的,他在判断key是不是重复的时候就判断了h ...
- 遍历并remove HashMap中的元素时,遇到ConcurrentModificationException
遍历并remove HashMap中的元素时,遇到ConcurrentModificationException for (Map.Entry<ImageView, UserConcise> ...
- [改善Java代码]减少HashMap中元素的数量
在系统开发中我们经常会使用HashMap作为数据集容器,或者是用缓冲池来处理,一般很稳定,但偶尔也会出现内存溢出的问题(OutOfMemory错误),而且这经常是与HashMap有关的.而且这经常是与 ...
- Java学习笔记--HashMap中使用object做key的问题【转】
在HashMap中,如果需要使用多个属性组合作为key,可以将这几个属性组合成一个对象作为key.但是存在的问题是,要做get时,往往没办法保存当初put操作时的key object的referenc ...
- K:HashMap中hash函数的作用
在分析了hashCode方法和equals方法之后,我们对hashCode方法和equals方法的相关作用有了大致的了解.在通过查看HashMap类的相关源码的时候,发现其中存在一个int has ...
随机推荐
- GitHub Top 微信小程序——在家中憋了几天写点代码吧
GitHub Top 本项目为 GitHub 热点项目微信小程序客户端,首页仅推荐一个热点项目,这个项目往往是社会热门事件所催生的一个项目,如 996.ICU.wuhan2020,所推荐项目标准为:积 ...
- Centos与Ubuntu
共同点 1.两个系统都分别有桌面系统与服务器系统,不过ubuntu的桌面从外观上来看要比centos的漂亮 不同点 1.centos中新建的普通用户是没有sudo权限的,如果想让普通用户拥有sudo权 ...
- tomcat梳理
tomcat梳理 Tomcat的缺省端口是多少,怎么修改? 默认接口是8080 修改 1)找到Tomcat目录下的conf文件夹 2)进入conf文件夹里面找到server.xml文件 3)打开ser ...
- openlayer3 坐标系转换
'EPSG:4326'-经纬度坐标-WGS84'EPSG:3857'- xy坐标-web墨卡托 ol3默认的坐标系为3857,即在创建ol.map的时候,若不指定projection,则默认为EPSG ...
- window nginx 中文路径, 文件名乱码问题解决
window nginx 中文路径, 文件名乱码, error, not found 此问题是由于windows系统编码与nginx编码设置不一致导致的,因此我们要统一二者的编码 nginx编码设置 ...
- Python 入门基本知识
编码:是把机器语言翻译成人能看懂的语言 美国信息互换标准代码<<ASSIC>>这张表就是相当于语法表随着发展后面又出现了:gb2312 ——到—— gbk18030 AS ...
- 【WPF学习】第三十章 元素绑定——绑定到非元素对象
前面章节一直都在讨论如何添加链接两个各元素的绑定.但在数据驱动的应用程序中,更常见的情况是创建从不可见对象中提取数据的绑定表达式.唯一的要求是希望显示的信息必须存储在公有属性中.WPF数据绑定数据结构 ...
- 惠普电脑win10关闭自动调节亮度
自动调节亮度真的太烦人了,突然从亮的画面变暗,又从暗的亮度变量,眼睛受不了.但是试了很多种方法都不行. 方法 第一种: 有一些电脑是有在设置--->显示界面--->有一个 关闭自动调节 按 ...
- C语言之灵魂 指针学习
指针是c语言的难点 称之为c语言的灵魂一点也不为过,不过指针用好了能事半功倍,用不好bug满天飞. 一.指针的概念 指针也是变量只不过是特殊的变量,指针的值是另一个变量的地(也就是变量所在的内存地址) ...
- 为什么用nginx:它的5个主要优点
1.高并发,高性能 2.可扩展性好啊 3.高可靠性 4.热部署 5.BSD许可证