首页 技术 正文
技术 2022年11月15日
0 收藏 543 点赞 5,075 浏览 1497 个字

1.hashmap中hash函数的实现中,异或运算操作的结果是什么,为什么要做这样的异或运算

    static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

假设h是 1000010001110001000001111000000,h>>>16的结果就是一个新的32位数,高16位为0,低16位为h的高16位,这个新数记为q,h^q的结果记为r,以方便描述

由于异或运算的特点,r的高16位就是h的高16位,r的低16位,就是h的低16位和h的高16位进行异或运算的结果

为什么要这样做呢,因为在putVal函数里,在为newNode找坑时,下标 i = (n – 1) & hash ,之所以要这样去计算i,是因为hash值是一个可能大于table数组大小的值,为了解决越界问题,也可以用取模的方式计算出合适的i,但是取模运算没有与运算效率高,而这里的与运算可以达到类似的效果,让计算出的i不会越界

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}

同时这也引出一点,就是为什么table的数组被要求是2的幂。

HashMap里table的初始大小是16, 二进制也就是 16-1=15,二进制表示是 1111,和hash值与运算,能保留hash值低4位的值,相当于保留了此前hash的散列结果

如果将HashMap里table的初始大小设置位17,17 – 1 = 16,二进制表示是10000,和hash值与运算,会破坏hash值的本身的结果,显然不会是一个好的散列方式

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,947
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,474
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,287
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,102
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,734
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,769