Java 组合字符串哈希和长字符串哈希

Java 组合字符串哈希和长字符串哈希,java,Java,我有以下java类: public class Person{ String name; //a unique name Long DoB; //a unique time . . . @Override public int hashCode(){ return name.hashCode() + DoB.hashCode(); } } 我的hashCode方法是否正确,即是否返回所有组合的唯一数字 我觉得我在这里遗漏了一

我有以下java类:

public class Person{
   String name;  //a unique name
   Long DoB;     //a unique time
   .
   .
   .
   @Override
   public int hashCode(){
     return name.hashCode() + DoB.hashCode();
   }

}
我的hashCode方法是否正确,即是否返回所有组合的唯一数字

我觉得我在这里遗漏了一些东西。

您可以让java.util.Arrays为您做这件事:

return Arrays.hashCode(new Object[]{ name, DoB });
您可以让java.util.Arrays为您完成以下任务:

return Arrays.hashCode(new Object[]{ name, DoB });

除了显而易见的问题之外,您可能还想实现equals方法

两个散列码求和的int溢出风险很小 求和本身似乎是一种提供唯一哈希代码的弱方法。相反,我会尝试一些逐位操作并使用种子。
除了显而易见的问题之外,您可能还想实现equals方法

两个散列码求和的int溢出风险很小 求和本身似乎是一种提供唯一哈希代码的弱方法。相反,我会尝试一些逐位操作并使用种子。
通常哈希代码是这样构建的:

   @Override
   public int hashCode(){
     return name.hashCode() ^ DoB.hashCode();
   }
但是,在使用hashcode方法时,需要记住的重要一点是它的使用。hashcode方法的使用是使用hashcode将不同的对象放入hashtable或其他集合中的不同bucket中。因此,有一种方法在较低的运行时间内为不同的对象提供不同的答案是不必要的,但不必对每个项目都有所不同,尽管这样更好

其他代码在存储或操作 实例–这些值应均匀分布在不同的情况下 输入,以便在集群中使用。这个属性对我们很重要 哈希表和其他存储数据的数据结构的性能 基于计算出的哈希值的组存储桶中的对象

此方法的重写实现的一般契约是 它们的行为方式与同一对象的相等方式一致 方法:给定对象必须一致地报告相同的哈希 值,除非对其进行更改以便不再使用新版本 被认为等于旧的,和那两个相等的物体 表示相等的值必须报告相同的哈希值


通常哈希代码是这样构建的:

   @Override
   public int hashCode(){
     return name.hashCode() ^ DoB.hashCode();
   }
但是,在使用hashcode方法时,需要记住的重要一点是它的使用。hashcode方法的使用是使用hashcode将不同的对象放入hashtable或其他集合中的不同bucket中。因此,有一种方法在较低的运行时间内为不同的对象提供不同的答案是不必要的,但不必对每个项目都有所不同,尽管这样更好

其他代码在存储或操作 实例–这些值应均匀分布在不同的情况下 输入,以便在集群中使用。这个属性对我们很重要 哈希表和其他存储数据的数据结构的性能 基于计算出的哈希值的组存储桶中的对象

此方法的重写实现的一般契约是 它们的行为方式与同一对象的相等方式一致 方法:给定对象必须一致地报告相同的哈希 值,除非对其进行更改以便不再使用新版本 被认为等于旧的,和那两个相等的物体 表示相等的值必须报告相同的哈希值


您可能还希望使用更流畅、更具NPE防弹性的工具,如:

编辑:


IntelliJ IDEA和Eclipse可以生成更高效的哈希代码和equals。

您可能还希望使用更流畅、更防NPE的工具,如:

编辑:


IntelliJ IDEA和Eclipse可以生成更高效的哈希代码和equals。

请参阅Bloch的高效Java 9

但是您应该从一个初始值开始,以便后续的零值是有效的,并将应用于结果的字段与乘数结合起来,以便顺序是有效的,这样类似的类将具有不同的散列

此外,您还必须对长字段和字符串等内容进行稍微不同的处理。e、 例如,对于long:

(int) (field ^ (field>>>32))
这意味着:

@Override public int hashCode() {
   int result = 17;
   result += name.hashCode() == null ? 0 : name.hashCode();
   result = 31 * result + (int) (DoB ^ (DoB >>> 32));
   return result;
}

31有点神奇,但奇数素数可以使编译器更容易优化移位减法的数学运算。或者您可以自己做移位减法,但为什么不让编译器来做呢。

请参阅Bloch的高效Java 9

但是您应该从一个初始值开始,以便后续的零值是有效的,并将应用于结果的字段与乘数结合起来,以便顺序是有效的,这样类似的类将具有不同的散列

此外,您还必须对长字段和字符串等内容进行稍微不同的处理。e、 例如,对于long:

(int) (field ^ (field>>>32))
这意味着:

@Override public int hashCode() {
   int result = 17;
   result += name.hashCode() == null ? 0 : name.hashCode();
   result = 31 * result + (int) (DoB ^ (DoB >>> 32));
   return result;
}
31有点神奇,但奇数素数可以使编译器更容易优化移位减法的数学运算。或者你可以自己做移位减法,但为什么不让
编译器执行此操作。

您的哈希代码实现良好且正确。如果您遵循其他人提出的任何建议,可能会更好,但它符合哈希代码的约定,冲突的可能性也不是特别大,尽管可以降低冲突的可能性。

您的哈希代码实现是正确的。如果您遵循其他人提出的任何建议,可能会更好,但它符合哈希代码的约定,冲突的可能性也不是特别大,尽管可以降低冲突的可能性。

equals覆盖。你可能想把长乘以一些奇怪的东西,例如,31。不,不会的。hasha+hashb!=哈沙+b。虽然不是很容易做到,但有人可能会找到一个完全不同的字符串,它散列到与组合的hasha+hashb相同的值。@DaveNewton我也有相同的覆盖。我应该把它添加到问题中吗?@nafas不,这更像是确保你做了正确的评论。不过,我可以补充一点,您拥有它是为了避免不可避免的堆积。它不可能是唯一的—仅在DoS中有比可能的哈希更多的long,而且它不一定是唯一的。问题应该是:它足够独特吗?等号优先。你可能想把长乘以一些奇怪的东西,例如,31。不,不会的。hasha+hashb!=哈沙+b。虽然不是很容易做到,但有人可能会找到一个完全不同的字符串,它散列到与组合的hasha+hashb相同的值。@DaveNewton我也有相同的覆盖。我应该把它添加到问题中吗?@nafas不,这更像是确保你做了正确的评论。不过,我可以补充一点,您拥有它是为了避免不可避免的堆积。它不可能是唯一的—仅在DoS中有比可能的哈希更多的long,而且它不一定是唯一的。问题应该是:它足够独特吗?+1我没有显示equals方法,它与你的方法几乎相同,只是我没有检查o是否为空。+1我没有显示equals方法,它与你的方法几乎相同,只是我没有检查o是否为空。