【发布时间】:2019-10-10 09:26:02
【问题描述】:
我有以下课程
public class Animal {
private int hash;
public Animal(int hash) {
this.hash = hash;
}
@Override
public int hashCode() {
System.out.println(hash);
return hash;
}
}
还有这段代码
public static void main(String[] args) {
Map<Animal, Integer> map = new HashMap<>();
for (int i = 0; i < 4; i++) {
map.put(new Animal(16 * i), i);
}
Animal an = new Animal(16*4);
map.put(an, 1);
for (int i = 5; i < 9; i++) {
map.put(new Animal(16 * i), i);
}
Integer value = map.get(an);
}
据我了解,所有这些值都应该放在一个存储桶中(由于它们的哈希码)。在最后一次调用map.get(an) 时,hashCode() 仅被调用一次(根据控制台),但在遍历存储桶并找到具有正确 hashCode() 的条目时不应该多次调用它吗?
EDIT1:如果我实现equals(带有控制台日志记录),它也不会被调用(再次根据控制台),只有当有两个具有 same 哈希码的对象时才会调用它(例如,如果我将它添加到我的代码 map.put(new Animal(16*3), 4);,并且在这种情况下,hashCode() 在从地图中获取对象时被调用 两次。
【问题讨论】:
-
请注意,您没有实现
equals。 -
为什么你认为它们都应该在同一个桶中?您创建的
Animal实例的 hashCode 值大多不同,为什么它们会有哈希冲突? -
除此之外:
HashMap缓存了它存储的键的哈希码,因此它只需要在添加键时调用一次hashCode。 -
@JoachimSauer index_of_bucket= hashCode(key) & (n-1), 我的 hashCodes 是 0, 16, 32 ... 而 n (map 的大小) 默认是 16
-
@BogdanTimofeev:这不是 Java
HashMap使用哈希的方式,它实际上在使用它之前对其进行了操作。检查您最喜欢的 JVM 实现中的私有HashMap.hash(Object)方法。