HashMap 中hash table 定位算法:
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
其中indexFor和hash源码如下:
/**
* 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);
}
indexFor这个方法论坛中已有人分析过,这里就不再分析。
现在分析一下hash算法:
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
假设key.hashCode()的值为:0x7FFFFFFF,table.length为默认值16。
上面算法执行如下:
得到i=15
其中h^(h>>>7)^(h>>>4) 结果中的位运行标识是把h>>>7 换成 h>>>8来看。
即最后h^(h>>>8)^(h>>>4) 运算后hashCode值每位数值如下:
8=8
7=7^8
6=6^7^8
5=5^8^7^6
4=4^7^6^5^8
3=3^8^6^5^8^4^7
2=2^7^5^4^7^3^8^6
1=1^6^4^3^8^6^2^7^5
结果中的1、2、3三位出现重复位^运算
3=3^8^6^5^8^4^7 -> 3^6^5^4^7
2=2^7^5^4^7^3^8^6 -> 2^5^4^3^8^6
1=1^6^4^3^8^6^2^7^5 -> 1^4^3^8^2^7^5
算法中是采用(h>>>7)而不是(h>>>8)的算法,应该是考虑1、2、3三位出现重复位^运算的情况。使得最低位上原hashCode的8位都参与了^运算,所以在table.length为默认值16的情况下面,hashCode任意位的变化基本都能反应到最终hash table 定位算法中,这种情况下只有原hashCode第3位高1位变化不会反应到结果中,即:0x7FFFF7FF的i=15。
- 大小: 238.6 KB
分享到:
相关推荐
通过上述分析,我们可以看到不同哈希函数构造方法的特点和优缺点。选择合适的哈希函数对于提高`HashMap`的性能至关重要。在实际应用中,可以根据具体场景的需求来选择最合适的哈希函数,或者通过组合多种哈希函数来...
这里我们将详细讨论在HashMap扩容时`rehash`方法中`(e.hash & oldCap) == 0`这一算法的推导。 首先,`e.hash`是HashMap中某个元素的哈希值,它由键对象的`hashCode()`方法计算得出,通常是键对象的哈希码右移16位后...
### HashMap的Hash原理详解 #### 一、概述 在Java编程语言中,`HashMap`是实现`Map`接口的...通过以上分析,我们可以更加深入地理解`HashMap`内部的工作机制,这对于理解和优化基于`HashMap`的应用程序具有重要意义。
HashMap之resize()方法源码解读 HashMap的resize()方法是HashMap中最核心的方法之一,该方法负责扩容HashMap的容量,以便存储更多的键值对。下面我们将对HashMap的resize()方法进行源码解读,了解其扩容机制和原理...
在本文中,我们将对 HashMap 的 put 方法的源码进行详细解读,分析put 方法源码中的内在逻辑关系,欣赏源码独特之美,从中学习更为精致的编程思维。 首先,让我们看一下 put 方法的源码: ```java public V put(K ...
当向 HashMap 中插入一个键值对时,会先计算键的哈希值,通过哈希值与数组长度进行按位与运算(hash % array.length),得到的余数值作为数组的索引。如果该索引位置已经有元素存在,说明发生了哈希冲突,此时会将...
下面我们将深入探讨 HashMap 的数据结构、 put 方法的实现细节和 Hash 码的计算过程。 HashMap 的数据结构 HashMap 的数据结构可以分为两部分:数组和链表。数组是 HashMap 的基本结构,链表是数组元素的具体实现...
紧接着,文档给出了HashMap中不同索引位置桶内的元素的具体信息,包括元素的哈希值(hash)和值(value)。例如,table[51]索引位置有两个元素,它们的哈希值分别为1635379和1577523,对应的值分别为63和70。通过...
本资源详细介绍了 Java 中的 HashMap 类,包括其实现机制、Hash 存储机制、集合存储机制等方面的知识点。 1. HashMap 和 HashSet 的关系 HashMap 和 HashSet 是 Java Collection Framework 的两个重要成员,虽然...
Java集合专题总结:HashMap和HashTable源码...本文总结了HashMap和HashTable的源码学习和面试总结,涵盖了它们的存储结构、构造方法、get和put方法的源码分析、Hash表的特点和缺点、HashTable和HashMap的区别等内容。
HashMap 是基于哈希表(Hash Table)实现的,哈希表是一个存储键值对的数据结构,它使用哈希函数将键转换为索引,然后将键值对存储在数组中。HashMap 使用链表来解决哈希冲突的问题,即当两个键的哈希值相同时,...
通过以上分析,我们可以看到Java 1.8 HashMap的put方法在处理哈希冲突时,不仅使用了链表,还在节点数量达到一定阈值时切换为红黑树,有效提高了数据结构的性能。同时,通过扩容机制,HashMap能够保持较低的哈希冲突...
标题"HashMap-master.zip_hash"可能指的是一个关于HashMap实现或优化的项目,其中包含了哈希函数的设计和分析。 哈希表的核心思想是通过哈希函数将键(Key)映射到数组的特定位置,使得我们能够以近乎常数的时间...
本文将深入分析HashMap和HashSet的哈希存储机制。 首先,HashSet是一个基于哈希表实现的无序不重复元素集合。它通过计算对象的哈希码来决定元素的存储位置,从而确保了快速的查找和插入操作。在HashSet中,元素的...
如果在计算出的位置上有现成的Entry存在(即发生哈希冲突),HashMap将遍历这个冲突链,检查是否已经存在一个键与新传入的键相等(通过调用equals()方法)。如果存在,它将替换掉旧的值,并返回旧值。如果不存在,它...
HashMap的工作原理基于哈希函数,它将键(Key)转化为一个哈希码(Hash Code),这个哈希码用于确定键值对在数组中的位置。当两个不同的键经过哈希函数处理后得到相同的哈希码时,就会发生哈希碰撞。为了解决这个...
final int hash; Entry,V> next; ... } ``` 当向HashMap中添加元素时,系统会根据键的哈希值计算出其在数组中的位置,并将元素存放在该位置。如果该位置已有元素,则将新元素以链表形式连接到已有元素之后。 ##...