请考虑以下代码段:
public class MainClass {
public static void main(String[] arg) {
Map<String, Object> map = new HashMap<>();
map.put("ONE", new BigInteger("1"));
map.put("TWO", new BigInteger("2"));
map.put("THREE", new BigInteger("3"));
map.put("FOUR", new BigInteger("4"));
map.put("FIVE", new BigInteger("5"));
map.put("SIX", new BigInteger("6"));
System.out.println("Hello !");
}
结果是:
size
为6。地图的table
包含以下内容:
[FIVE=5,
SIX=6,
ONE=1,
TWO=2,
THREE=3]
FOUR
消失了。正如之前所述的评论,计算我的条目的hashCode
是明智的,以模块的大小为模。它给出了以下结果:
ONE : 0
TWO : 0
THREE : 1
FOUR : 2
FIVE : 3
SIX : 4
正如我们所看到的,hashCode
并未表明考虑FOUR
与任何值的冲突。这也适用于ConcurrentHashMap
和LinkedHashMap
,因此我认为这是一个HashMap
问题。
有人可以向我解释实际发生了什么吗?我很遗憾这个。
我正在使用:
答案 0 :(得分:4)
&#34; FOUR&#34;并没有消失。您亲眼看到地图的大小为6,如果您打印地图,则会看到所有6个条目。
如果你在调试器中仔细观察,你会看到那些键&#34; ONE&#34;和&#34;四&#34;映射到同一个桶(索引7)。即使他们没有相同的哈希码,也会发生这种情况(因为HashMap
会对密钥的hashCode()
执行一些额外的计算,然后对结果执行% table.length
获取桶的索引。)
在您的示例中,为&#34; ONE&#34;计算的哈希值是&#34;四&#34;是78407由于默认的初始桶数为16,因此桶的计算方式为78407%16 == 2163975%16 == 7,因此两个密钥都存储在同一个桶中。
答案 1 :(得分:4)
HashMap
的内部表(实际上是一个简单的数组)不存储值,而是存储类似结构的结构,其元素现在存储多个值。
哈希映射计算放入其中的键的哈希值。具有相同哈希码的不同键进入同一列表(在表数组中编入索引)。
查看HashMap.Node
的源代码:
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
...
}
该列表中的每个节点都存储密钥,值,哈希码以及指向该列表下一个节点的指针。
您的示例代码构建了下表:
[2] FIVE = 5 => null
[3] SIX = 6 => null
[7] ONE = 1 => FOUR = 4 => null
[13] TWO = 2 => null
[15] THREE = 3 => null
顺便说一下......打印整个地图会产生以下结果:
{FIVE=5, SIX=6, ONE=1, FOUR=4, TWO=2, THREE=3}