简体   繁体   English

为什么HashMap(JDK1.8)中的hash计算不需要像ConcurrentHashMap那样考虑负hashCode?

[英]Why the calculation of hash in HashMap(JDK1.8) don't need to consider the negative hashCode as ConcurrentHashMap does?

In HashMap : (h = key.hashCode()) ^ (h >>> 16);HashMap(h = key.hashCode()) ^ (h >>> 16);

In ConcurrentHashMap : (h ^ (h >>> 16)) & HASH_BITS;ConcurrentHashMap(h ^ (h >>> 16)) & HASH_BITS;

where HASH_BITS is 0x7fffffff , by & HASH_BITS it can always be a positive number.其中HASH_BITS0x7fffffff ,通过& HASH_BITS它总是可以是正数。

Why the calculation of hash in HashMap(JDK1.8) don't need to consider the negative hashCode as ConcurrentHashMap does?为什么HashMap(JDK1.8)中的hash计算不需要像ConcurrentHashMap那样考虑负hashCode?

Ultimately, the case where the hash is negative (after spreading) does need to be considered in the HashMap case as well.最终,在HashMap情况下需要考虑散列为负(传播后)的情况。 It is just that this happens later in the code.只是这发生在代码的后面。

For example, in getNode (Java 8) you find this:例如,在getNode (Java 8) 中,您会发现:

    Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (first = tab[(n - 1) & hash]) != null) {

Since tab.length is a power of 2, tab.length - 1 is a suitable bitmask for reducing hash to a subscript for the array.由于tab.length是 2 的幂,因此tab.length - 1是一个合适的位掩码,用于将hash减少到数组的下标。

You can rest assured that in every implementation of HashMap or ConcurrentHashMap there is some code that reduces the hash code to a number that is suitable for use as a subscript.您可以放心,在HashMapConcurrentHashMap每个实现中,都有一些代码可以将哈希码简化为适合用作下标的数字。 It will be there ... somewhere.它会在那里……某个地方。

But also ... don't expect the code of these classes to be easy to read.但也...不要指望这些类的代码很容易阅读。 All of the collection classes have been reworked / tuned multiple times get the best possible (average) performance over a wide range of test cases.所有集合类都经过多次重新设计/调整,在各种测试用例中获得最佳(平均)性能。

Actually it handles negative index calculations.实际上它处理负指数计算。 It's not evident at first looking but there are calculations in some places while accessing the elements(key or value).乍一看并不明显,但在访问元素(键或值)时在某些地方进行了计算。

int index = (n - 1) & hash , in which n is length of the table int index = (n - 1) & hash ,其中n是表的长度

It simply handles negative indexing.它只是处理负索引。

AFAIK, HashMap always uses arrays sized to a power of 2 (eg 16 , 32 , 64 , etc.). AFAIK, HashMap总是使用大小为 2 的幂的数组(例如163264等)。

Let's assume we have capacity of 256 ( 0x100 ) which is 2^8 .假设我们的容量为256 ( 0x100 ),即2^8 After subtraction 1, we get 256 - 1 = 255 which is 0x100 - 0x1 = 0xFF The subtraction gives rise to get the proper bucket index between 0 to length-1 with exact bit mask needed to bitwise-and with the hash.减 1 后,我们得到256 - 1 = 255 ,即0x100 - 0x1 = 0xFF减法产生了在0length-1之间获得正确的桶索引,以及按位和散列所需的精确位掩码。

256 - 1 = 255
0x100 - 0x1 = 0xFF

A hash of 260 ( 0x104 ) gets bitwise-anded with 0xFF to yield a bucket number of 4 . 260 ( 0x104 ) 的散列与0xFF进行按位与运算以产生桶号4

A hash of 257 ( 0x101 ) gets bitwise-anded with 0xFF to yield a bucket number of 1 . 257 ( 0x101 ) 的散列与0xFF进行按位与运算以产生桶号1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM