hashmap中的哈希和索引方法

时间:2020-02-23 14:34:48  来源:igfitidea点击:

在本教程中,我们将看到HashMap内部在内部运行的哈希和索引。
哈希和索引属于HashMap类。
当Key对象有自己的Hashcode方法时,JDK开发人员需要有另一个哈希函数。
让我们看看哈希和索引的代码

/**
 * Applies a supplemental hash function to a given hashCode, which
 * defends against poor quality hash functions.  This is critical
 * because HashMap uses power-of-two length hash tables, that
 * otherwise encounter collisions for hashCodes that do not differ
 * in lower bits. Note: Null keys always map to hash 0, thus index 0.
 */
static int hash(int h) {
    //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);
}
 
/**
 * Returns index for hash code h.
 */
static int indexFor(int h, int length) {
    return h & (length-1);
}

正如Java Doc所说的那样,关于哈希:将补充哈希函数应用于给定的哈希码,这捍卫质量差的哈希函数。
这是至关重要的,因为HashMap使用两个长度哈希表,否则遇到对较低位不同的散列码的冲突。
注意:NULL键始终映射到HASH 0,从而索引0。

让我们通过示例来理解这一点:假设key对象的hashcode()只返回3个值31,63和95. 31,63和95是整数,所以所有是32位。
31 = 00000000000000000000000000011111 63 = 00000000000000000000000000111111 95 = 00000000000000000000000001011111现在让我们说我们的散列映射的lenth是16(2 ^ 4,哈希映射的长度将是总是在两个功率)

如果我们不使用哈希函数怎么办:

现在,如果我们不使用哈希函数然后

索引将返回:

31 = 0000000000000000000000000000000000000000/11 = 15 6311111 = 1111 = 111111 = >> 11

为什么这样?
因为当我们调用indexfor函数时,它将在31和15,63和15和95和15之间进行。
对于前任。
如下(2 ^ N-1)将始终拥有1的序列。
因此,它在此处最重要的是0和1始终为0.在上面的例子中,所有人都有1111即将返回的原因指数。
因此,虽然我们有不同的哈希码,但每个条目对象将仅存储在15个索引中。

如果我们使用哈希函数怎么办:

如果我们使用哈希函数,那么

在每个哈希码上,将应用第一个哈希。

31 = 00000000000000000000000000011111 => 00000000000000000000000000011110 63 = 00000000000000000000000000111111 => 00000000000000000000000000111100 95 = 00000000000000000000000001011111 => 00000000000000000000000001011010

现在将新的哈希传递新散列后。
它将返回:1110 = 10

在应用哈希函数之后,返回不同的索引返回不同的索引,所以哈希函数是重新分配HashMap中的元素,因此较少的冲突和更好的性能。
散列操作的主要目的是使散列码在最低有效位中可见,使得HashMap元素可以均匀地分布在铲斗中

说明:

  • 如果两个关键对象具有相同的哈希码,那么它们将始终在表数组中转到相同的索引
  • 如果两个关键对象没有相同的哈希码,那么它们可能会或者可能不会在表阵列中转到相同的索引。