Java:获取对象的唯一哈希值
我试图为Java对象获取唯一的哈希值,如下所示:Java:获取对象的唯一哈希值,java,Java,我试图为Java对象获取唯一的哈希值,如下所示: 如果A==B,则A.HashValue()==B.Hash.HashValue() 如果是B然后A.HashValue()!=B.HashValue() 假设对象包含几个布尔和整数字段。使用System.identityHashCode() 编辑:使用此方法确实不能保证哈希代码的唯一性;然而,我认为这是最好的,因为你不能得到一个对象的内存位置。您提出的任何其他散列函数都必须具有两个结构等效的对象散列为相同值的属性,而此函数至少为您提供了程序创建
如果A==B,则A.HashValue()==B.Hash.HashValue()
如果是B然后A.HashValue()!=B.HashValue()
假设对象包含几个布尔和整数字段。使用
System.identityHashCode()
编辑:使用此方法确实不能保证哈希代码的唯一性;然而,我认为这是最好的,因为你不能得到一个对象的内存位置。您提出的任何其他散列函数都必须具有两个结构等效的对象散列为相同值的属性,而此函数至少为您提供了程序创建的所有对象都具有不同散列码的机会
为了完整性:在构建对象时,从其初始内存位置计算一次对象的默认哈希代码。因此,如果使用相同的初始内存位置创建了多个对象,则它们必然具有相同的哈希代码。这通常是不可能的,您必须保证如果
a.equals(b)
,则a.hashCode()==b.hashCode()
。您不能保证相反的结果:因为hashCode方法只有32位的空间,而JVM可以有64位的空间来存放标识hashCode,所以总是会发生冲突。//非常重要的编辑
Gjorgji,我知道你认为下面的答案是正确的,但我发现它是不正确的
如果您有这样一个类:
class tiny {
int a;
public int hashCode() { return a; }
}
您已经将所有可能的哈希代码都设置为最大值。(如果不清楚原因,请说明。)
因此,如果您向对象添加更多信息,如果您希望在hashCode中表示这些信息,那么您将在某个地方发生冲突
但是,就这一点而言,您并不是真的想要得到一个对象100%唯一的哈希代码。这真的不是hashCode的重点
hashCode的目的是为对象提供一个“足够唯一”的标识符,以便将其放入哈希桶中。与其说是鉴定,不如说是分类。这个想法是,如果你有一大堆的对象,你可能不会有太多的碰撞,所以如果你按照它们的哈希代码对项目进行分组,你可能会非常快地访问到你想要的东西
如果这意味着你取消选择我的答案为正确,那没关系。这真的不符合你的要求。我希望您能意识到,这个对hashCode的解释将引导您找到正确的用法,从而保持正确性。但正如马克明确指出的,这实际上并不能解决你所说的问题
以下是旧答案:
===========================================================
这里有一篇关于它的好文章,来自effectivejava(这里有最好的“我想学习如何成为一名优秀的Java开发人员”一书)
如何获得“唯一ID”-我不建议这样做,但它确实满足了问题中的要求。请参阅并考虑弱引用。
Object.toString
(基本方法)在每个对象的生命周期中都会返回一个唯一的字符串。“编码的数字”可以被虹吸出来,是AFAIK的“内部参考”
我不保证上一段的准确性。YMMV。愉快的编码。如果您可以将类的实例数限制在232以下,就可以做到这一点。这里有一个方法:
import java.util.concurrent.atomic.AtomicInteger;
class UniqueHash {
private static AtomicInteger NEXT_HASH_CODE = new AtomicInteger();
private final int hashCode;
UniqueHash() {
while (true) {
int nextHashCode = NEXT_HASH_CODE.get();
if (nextHashCode == -1) {
throw new RuntimeException("Too many instances!");
}
if (NEXT_HASH_CODE.compareAndSet(nextHashCode, nextHashCode + 1)) {
hashCode = nextHashCode;
break;
}
}
}
public int hashCode() {
return hashCode;
}
}
编辑1:这是假设“a==b”是指对象标识意义上的a==b
。您在评论中提到,如果字段相等,您实际上是指。请参阅@Mark Peters和@sjr的回复
编辑2:修复了@Tom Hawtin-tackline指出的错误,保留了其他错误做法。:)
编辑3:我的“修复”中有一场比赛。修正了比赛
我试图为Java对象获取一个唯一的哈希值……假设该对象包含几个布尔和整数字段
若要执行此操作,则需要大于32位整数的长度,或者需要在字段范围上定义约束。要将超过32位的信息塞进32位是不可能的,仅一个int和一个boolean就是33位的信息(假设int的每个值都是可能的)
如果有多个int字段,long
甚至不够大。您需要进入biginger
、位集
或字节数组
无论如何,假设您的数据跨度不超过32位。然后,只需将数据排列到由int表示的位字段中
byte a;
byte b;
boolean c;
boolean d;
int hash = (a << 24) | (b << 16) | (c ? 0x02 : 0) | (d ? 0x01 : 0);
//layout
//index: ... 3210
//aaaa aaaa bbbb bbbb 0000 0000 0000 00cd
字节a;
字节b;
布尔c;
布尔d;
It hash =(a)你是指java操作符意义上的代码> >代码>和>代码>?= />代码,或者你是指在更抽象的意义上?我考虑= =,所有对象的字段都是相同的。你应该注意到,这意味着A.Erras(B),而不是A==B:),这是否保证了每个对象的唯一性(如果对象不相等)?我之所以这么问,是因为System.HashCode()不能保证:@Giorgio的操作与Object.HashCode()相同,即使它重载了。请注意,两个不同的对象可能仍然具有相同的哈希代码。但是,如果a==b
则identityHashCode(a)==identityHashCode(b)
独立于任何hashCode/equals
覆盖。您不能依赖于此,对吗?identityHashCode是一个int,JVM可能是64位的,因此仍然可能存在冲突
byte a;
byte b;
boolean c;
boolean d;
int hash = (a << 24) | (b << 16) | (c ? 0x02 : 0) | (d ? 0x01 : 0);
//layout
//index: ... 3210
//aaaa aaaa bbbb bbbb 0000 0000 0000 00cd