Java 如何在应用程序运行时保持对象的哈希代码一致?

Java 如何在应用程序运行时保持对象的哈希代码一致?,java,hashcode,Java,Hashcode,假设我们有以下简单的可变类: 使用only class字段x和y重写hashCode方法将不起作用,因为调用addToX/addToY方法时,值可能会在运行时更改 所以我想知道对于可变类,hashCode的适当实现是什么?假设在点#等于(点p)的实现中使用x和y字段,那么就没有必要在点类型的对象的生命周期内保持点#hashCode()的一致性 实际上,类java.lang.Object的javadoc为hashCode()声明 当在一个过程中对同一对象多次调用时 在执行Java应用程序时,has

假设我们有以下简单的可变类:

使用only class字段
x
y
重写
hashCode
方法将不起作用,因为调用
addToX
/
addToY
方法时,值可能会在运行时更改


所以我想知道对于可变类,
hashCode
的适当实现是什么?

假设在点#等于(点p)的实现中使用x和y字段,那么就没有必要在点类型的对象的生命周期内保持点#hashCode()的一致性

实际上,类java.lang.Object的javadoc为hashCode()声明

当在一个过程中对同一对象多次调用时 在执行Java应用程序时,hashCode方法必须一致 返回相同的整数

但在那之后有一次禁闭:

,前提是对象上的equals比较中未使用任何信息 修改


另请参见

假设在点#等于(点p)的实现中使用x和y字段,则无需在点类型的对象的生命周期内保持点#hashCode()一致

实际上,类java.lang.Object的javadoc为hashCode()声明

当在一个过程中对同一对象多次调用时 在执行Java应用程序时,hashCode方法必须一致 返回相同的整数

但在那之后有一次禁闭:

,前提是对象上的equals比较中未使用任何信息 修改


另请参见

您在问题中暗示的类并不真正表示静态点,因为您可以更改x和y值。这就是为什么基于x和y值的哈希代码对您来说似乎是错误的。我认为这个类真正代表的是一个x和y值可以改变的位置。在这种情况下,有一个属性表示该位置的标识(例如,37号车的位置),即使x/y值发生变化,该标识也不会发生变化。您希望定义此唯一值属性,将其添加到类中,并基于该属性实现哈希代码(和equals)

您在问题中暗示该类实际上并不表示静态点,因为您可以更改x和y值。这就是为什么基于x和y值的哈希代码对您来说似乎是错误的。我认为这个类真正代表的是一个x和y值可以改变的位置。在这种情况下,有一个属性表示该位置的标识(例如,37号车的位置),即使x/y值发生变化,该标识也不会发生变化。您想要定义这个唯一值的属性,将它添加到类中,并基于该属性实现哈希代码(和equals)

这是一个矛盾的目标。如果希望哈希代码是对象值的函数,并且对象值可能会更改,则必须接受哈希代码可能会更改。第一次计算哈希代码并将其存储在对象的字段中。在后续调用中使用该值。为什么不接受原始哈希代码?哈希代码不应该保持不变。它只应该与equals()一致(即两个相等的对象必须具有相同的hashCode)。这是一个矛盾的目标。如果希望哈希代码是对象值的函数,并且对象值可能会更改,则必须接受哈希代码可能会更改。第一次计算哈希代码并将其存储在对象的字段中。在后续调用中使用该值。为什么不接受原始哈希代码?哈希代码不应该保持不变。它只应该与equals()一致(即,两个相等的对象必须具有相同的哈希代码)。谢谢您的解释。对于类java.lang.Object的javadoc来说,使用类字段x和y实现散列代码(并将它们用于equals方法)似乎是可行的。但这不是错了吗,因为更改哈希代码可能会在使用哈希集(例如)时导致问题?@JohnThreepwood:不是。错的是将可变类的实例存储在哈希集中,然后修改它们。但这不是可变类的错。这就是使用它的代码的错误。@JBNizet:说得好。为了完成这一回答,这里有两个有用的链接,供任何人在对象存储在基于哈希的容器中后,想要了解更改对象哈希代码的影响的人使用:请参见此处[link]和此处:[link]。但是请注意,这些问题并不意味着hashCode()和equals()中通常不能有可变字段。感谢您的解释。对于类java.lang.Object的javadoc来说,使用类字段x和y实现散列代码(并将它们用于equals方法)似乎是可行的。但这不是错了吗,因为更改哈希代码可能会在使用哈希集(例如)时导致问题?@JohnThreepwood:不是。错的是将可变类的实例存储在哈希集中,然后修改它们。但这不是可变类的错。这就是使用它的代码的错误。@JBNizet:说得好。为了完成这一回答,这里有两个有用的链接,供任何人在对象存储在基于哈希的容器中后,想要了解更改对象哈希代码的影响的人使用:请参见此处[link]和此处:[link]。但是请注意,这些问题并不意味着在hashCode()和equals()中通常不能有可变字段。
public class Point {
  private int x;
  private int y;

  ...

  public void addToX(int delta) {
    x += delta;
  }

  public void addToY(int delta) {
    y += delta;
  }
}