我有由[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
问题:
这些人的哈希码在我的本地系统中使用的是相同的,但是当我将此代码推广到不同的环境时,它们将导致不同的哈希码。
我无法找出问题。所以寻求帮助!
我相信在比较两个TestIdentifier对象的用例中,使用equals()方法比较所有数据成员是一个更好的选择。原因是,hashcode()合同规定,在未修改对象且主要将其与哈希表一起使用时,在对象上调用此method()会返回相同的整数值。
Java合同明确规定:“从一个应用程序的执行到同一应用程序的另一执行,此整数不需要保持一致。”
如果需要阅读更多,请参考Java文档:https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()
非常老版本的龙目岛在哈希码算法中使用了稍有不同的质数;这已经更改了,因为它知道它可能会破坏一些现有的代码,这正是@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”,尽管与土耳其语不同,我认为语言环境设置实际上不会这样做)。