2016-03-08 73 views
1

到目前为止,我知道在哈希映射中重新哈希后,所有条目都会与新的表长度一起重新映射。但我想知道当我碰撞时会发生什么。重新散列后,存储在同一个存储桶中的元素是否可以重新分配为单独的存储桶?

例如

Map<String, String> map = new HashMap<>(5); 
map.put("a", "ape"); 
map.put("b", "bird"); 
map.put("c", "chicken"); 

想,他们有不同的哈希码,但"b""c"存储在内部哈希后同一个桶。

现在,我将插入一个第四条目到达负载因数因此重散列表:

map.put("d", "dynamite"); 

可以与碰撞的条目被存储在单独的桶或它们总是会在一起(在根据相反的顺序我读过的)?

我想这个标题的答案是否定的,因为我会得到相同的内部散列值 "b""c",但我不确定。

回答

1

在这里有两种方法可以查看碰撞。

一个是从hashCode()方法返回相同值的两个对象。在这种情况下,无论哈希表数组的大小如何,它们都会在同一个存储桶中结束。

另一种情况是两个对象具有不同的哈希码,但由于数组大小小于理论上可返回的唯一值,所以最终在同一个存储桶中。通常,原始散列码值将取模数组大小,并用于为条目查找正确的存储桶。假设初始数组大小为16,并且对象A的哈希码为3,对象B的哈希码为19.由于19%16 == 3,因此对象A和对象B将在同一个桶中结束。如果现在将数组大小调整为18,则对象A将以桶3%20 == 3结束,但对象B将以桶19%20 == 19结束。因此,现在它们处于不同的桶中,它们回答提出的问题标题带有“是”。

+0

谢谢,只是为了简洁¿位掩码和国防部给出了相同的结果? – EMER

+1

@EMER是的,假设我们使用了较短的散列,只有5位。对象A具有等于11000的散列码(二进制),对象B具有散列码10000.对于长度为8的数组,我们使用3位的位掩码,在两种情况下导致存储桶000。如果我们将数组大小增加到16,并使用4位作为掩码,则对象A将位于存储区1000中,但对象B将位于0000中:因此,它们将以不同的存储区结束,并且存储更大的数组。 –

1

根据表达式hashcode%容量所表示的数字是否保持相同的后置重新散列,它们可以存储在同一个桶或不同桶中。

E.g.假设字符串对象“b”和“c”返回的hashCodes是27和32.您的初始容量是5.所以对于“a”和“b”,表达式hashcode%容量等于2和2。因此他们都将被存储在同一个桶中。现在在重新哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈!假设新容量为10.因此,表达式hashcode%容量现在分别等于7和2。这意味着2个对象现在将在重新哈希后存储在单独的桶中。

现在考虑下面的情况。比方说,2个对象返回的hashCodes是27和37。在这种情况下,表达式散列码%容量在散列之前等于2和2,在散列之后等于7和7。所以他们仍然会被存储在同一个桶中。

+0

是的,它更有意义,使用模数更清晰。你和@MichałKosmulski给了我两个mod运算符的例子。但是,Java Collections Framework使用位掩码。反思在这我会假设给出了相同的结果,这是一个执行的问题 – EMER

相关问题