Java 可变对象的hashCode()是否有用途?
我一直在浏览Java集合框架的源代码,注意到Java 可变对象的hashCode()是否有用途?,java,hash,hashcode,Java,Hash,Hashcode,我一直在浏览Java集合框架的源代码,注意到AbstractList和AbstractMap将其元素的哈希代码之和作为自己的哈希代码值返回。这使得列表和映射实现根据集合的内容返回不同的哈希代码值 我知道的hashCode()方法的唯一用途是将元素均匀地分布到使用散列的数据结构内部的存储桶中,例如HashSet和HashMap。但是,Set和Map合同规定: 当对象是集合中的元素时,如果对象的值以影响相等比较的方式更改,则不会指定集合的行为 以及: 如果对象是贴图中的关键点时,对象的值以影响相等比
AbstractList
和AbstractMap
将其元素的哈希代码之和作为自己的哈希代码值返回。这使得列表和映射实现根据集合的内容返回不同的哈希代码值
我知道的hashCode()
方法的唯一用途是将元素均匀地分布到使用散列的数据结构内部的存储桶中,例如HashSet
和HashMap
。但是,Set
和Map
合同规定:
当对象是集合中的元素时,如果对象的值以影响相等比较的方式更改,则不会指定集合的行为
以及:
如果对象是贴图中的关键点时,对象的值以影响相等比较的方式更改,则不会指定贴图的行为
这些契约使得可能根据其状态返回不同散列值的对象在集合中使用和在映射中用作键时非常危险。这让我想知道:
hashCode()
方法除了在散列集合中使用之外还有什么用处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,您可能会遇到问题
您可以在实例化时在构造函数中生成它,就像它对字符串对象所做的那样
String的hashCode是按需生成的,以减少在不需要hashCode的地方创建字符串的开销。注意:除非有人试图创建哈希代码为0的字符串,否则拥有哈希代码为0的字符串虽然很少见,但代价很高
类似地,对象的hashCode也是按需生成的。它存储在Oracle/OpenJDK的标头中,未设置的初始值为0,但第一次使用时设置为1-2^31-1
此程序通过将hashCode重置为0,对Object.hashCode()
的成本进行基准测试
该程序使用更简单的策略对Object.HashCode()的设置进行基准测试
我的意思是,您需要根据最终字段生成它,所以哈希值不会改变
这还不足以保证哈希代码不发生变化,例如
class A {
final List<String> strings = new ArrayList<>();
public int hashCode() {
return strings.hashCode();
}
}
A类{
最终列表字符串=新的ArrayList();
公共int hashCode(){
返回字符串。hashCode();
}
}
您的字段必须是final
且不可变。以确保哈希代码不会更改。然而,如果你不改变它们,它们也不会改变
hashCode()
方法应该与其equals()
方法一致。如果一个类根据可变状态定义实例相等,那么它的hashCode()
也应该根据相同的可变状态定义
这样的对象很少适合包含在基于散列的集合中,但如果小心避免在它们留在集合中时对它们进行变异,则可以在这样的集合中使用它们
返回一个常量散列值不是更好吗
Object.hashCode()
事实上就是这样,假设您在每个实例的意义上指的是“常量”。如果您不重写equals()
,那么也没有很好的理由重写该常量散列值,但是如果您重写equals()
,那么您确实应该提供一致的hashCode()
实现
hashCode()方法除了在哈希集合中使用之外还有什么用途
如果一个类缓存了它计算出的散列码,那么比较实例的散列码可以作为一种廉价的“可能相等”测试,允许绕过更昂贵的exac