我一直在浏览 Java Collections 框架的源代码并注意到 AbstractList
和 AbstractMap
返回它们元素的哈希码的总和作为它们自己的哈希码值。这使得 List 和 Map 实现根据集合的内容返回不同的哈希码值。
据我所知,hashCode()
方法的唯一用途是将元素均匀分布到使用散列的数据结构内的桶中,例如HashSet
和 HashMap
。但是,Set
和 Map
契约指定:
The behavior of a set is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is an element in the set.
和:
The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map.
这些合约使得对象可能会根据其状态返回不同的哈希值,这对于在集合中使用和作为映射中的键是危险的。这让我想知道:
- 返回变量哈希值是否有意义?
- 返回一个常量(每个对象类)散列值不是更好吗?
hashCode()
方法除了用于哈希集合之外,还有什么用处?
最佳答案
Is there a point in returning a variable hash value?
数据结构不知道您是否更改了键或元素的哈希码。这样做会破坏数据结构。但是,如果您在将对象添加到哈希集合之前对其进行变异,并且之后不更改它,这将起作用。
Would not it be better to return a constant hash value?
是的,但该常量必须与 equals 一致,在这种情况下,返回常量的唯一方法是不更改用于创建 hashCode() 的任何字段。
What use can the hashCode() method have besides being used in hash collections
它可用于识别单个对象以用于调试/记录目的,但如果您使用内置的 Object.hashCode() 或 System.identityHashCode(),这会更有用。这是检查两个对象是否是相同引用的快速方法,例如
ByteBuffer bb = ByteBuffer.allocate(1024);
ByteBuffer bb2 = ByteBuffer.allocate(1024);
useBB(bb);
useBB(bb2);
public static void useBB(ByteBuffer bb) {
System.out.println(Thread.currentThread()+" - Using bb " + System.identityHashCode(bb));
// do something
}
如果你看到两个线程使用同一个 ByteBuffer,你可能有问题....
you can generate it in a constructor upon instantiation like its done for String objects.
String 的 hashCode 是按需生成的,以减少在不需要 hashCode 的地方创建 String 的开销。注意:拥有 hashCode 为 0 的 String 虽然很少见,但代价很高,除非有人尝试创建 hashCode 为 0 的字符串。
同理,Object的hashCode也是按需生成的。它存储在 Oracle/OpenJDK 的 header 中,初始值为 0 表示未设置,但在首次使用时设置为 1 - 2^31-1。
此程序通过将 hashCode 重置为 0 来对 Object.hashCode()
的成本进行基准测试。
此程序使用更简单的策略对 Object.HashCode() 进行基准测试。
I meant that you would need to generate it based on final fields, so hash would not change.
这不足以保证 hashCode 不会改变,例如
class A {
final List<String> strings = new ArrayList<>();
public int hashCode() {
return strings.hashCode();
}
}
您的字段必须是 final
和不可变的。以确保 hashCode 不会改变。但是,如果您不更改它们,它们也不会更改。
关于java - 可变对象的 hashCode() 是否有用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39597464/