Java哈希码在不同机器上的工作方式不同

问题描述 投票:1回答:2

我有由[lombok]生成的哈希码,并将其用作标识符。逻辑如下:

@EqualsAndHashCode
@AllArgsConstructor
@Getter
public final class TestIdentifier {

   private String firstName;
   private String lastName;
   private final LocalDate dob;

}

这是我创建对象的方式:

TestIdentifier testIdentifier = new TestIdentifier(
          StringUtils.lowerCase(value.getFirstName()),
          StringUtils.lowerCase(value.getLastName()),
          LocalDate.ofEpochDay(
              value.getDateOfBirth()));
testIdentifier.hashCode()

用例:考虑两个具有以下名字/姓氏和DOB的人。我希望它们的哈希值都相同。

Person1:

FIRSTNAME LASTNAME 2000-08-09

Person2:

姓氏2000-08-09

问题:

这些人的哈希码在我的本地系统中使用的是相同的,但是当我将此代码推广到不同的环境时,它们将导致不同的哈希码。

我无法找出问题。所以寻求帮助!

java spring lombok
2个回答
0
投票

我相信在比较两个TestIdentifier对象的用例中,使用equals()方法比较所有数据成员是一个更好的选择。原因是,hashcode()合同规定,在未修改对象且主要将其与哈希表一起使用时,在对象上调用此method()会返回相同的整数值。

Java合同明确规定:“从一个应用程序的执行到同一应用程序的另一执行,此整数不需要保持一致。”

如果需要阅读更多,请参考Java文档:https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()


0
投票

非常老版本的龙目岛在哈希码算法中使用了稍有不同的质数;这已经更改了,因为它知道它可能会破坏一些现有的代码,这正是@Pruthvik在回答中说的原因:您不应该依赖于不同VM调用之间的一致哈希码。

但是,听起来好像您为same VM调用获得了不同的哈希码,且字段大概相等-这不能归因于lombok。

这必须表示您的字段实际上不相等。至少,lombok通过为每个字段生成一个哈希码来生成哈希码; lombok为列出的所有3个字段生成“ sub”哈希码的方式都是相同的:只需在这些对象上调用hashCode()方法。因此,那些可能正在改变。

要调试,编写一个方法,分别打印出每个字段返回的哈希码。找到它们不同的地方,您将找到不同的对象。例如,如果您当前的语言环境是土耳其语,则大写的I将小写为无点i,因此,在所有VM上,"Jim".toLowerCase()均不等于"JIM".toLowerCase()。这听起来像是一个合理的解释。

我不知道为什么在繁琐的工作中将工作交给所有的apache库,但是我快速检查了一下文档,这个stringutils方法确实听起来毫无用处。它仅调用toLowerCase()。哪个确实存在这种“根据当前区域设置”的问题。尝试lowerCase(theInput, Locale.ENGLISH)

NB:您可以小写字符串以规范化比较的理论是一个误解。它可以用英语运行,但不适用于许多其他语言。除非您要遵循一条规则“除非该软件的所有用户都说英语,荷兰语,德语,丹麦语和其他几种西方语言,否则该软件将无法工作”,否则您可能希望减少对小写字母的依赖,然后再使用它来标识。而荷兰的事情可能甚至无法解决,他们正在发生奇怪的点缀Y事情。 (“ YPENBURG” .toLowerCase()在适当的荷兰语中应该应该是“ ijpenburg”,尽管与土耳其语不同,我认为语言环境设置实际上不会这样做)。

© www.soinside.com 2019 - 2024. All rights reserved.