hashmap中的哈希和索引方法
在本教程中,我们将看到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元素可以均匀地分布在铲斗中
说明:
- 如果两个关键对象具有相同的哈希码,那么它们将始终在表数组中转到相同的索引
- 如果两个关键对象没有相同的哈希码,那么它们可能会或者可能不会在表阵列中转到相同的索引。