最近我读了这篇文章 开发人员工作文件。

该文档是关于有效和正确地定义hashCode()和equals(),但我无法弄清楚为什么我们需要覆盖这两个方法。

我如何决定有效地实现这些方法?


当前回答

恕我冒昧,这是根据规则说的-如果两个对象相等,那么它们应该具有相同的哈希值,即相等的对象应该产生相同的哈希值。

如上所述,Object is ==中的默认equals()对地址进行比较,hashCode()返回整数形式的地址(对实际地址进行哈希),这对于不同的Object来说也是不同的。

如果你需要在基于哈希的集合中使用自定义对象,你需要覆盖equals()和hashCode(),例如如果我想维护员工对象的HashSet,如果我不使用更强的hashCode和equals,我可能最终会覆盖两个不同的员工对象,这发生在我使用年龄作为hashCode()时,但是我应该使用唯一的值,可以是员工ID。

其他回答

hashCode ():

如果只重写hash-code方法,什么也不会发生,因为它总是为每个对象返回一个新的hashCode作为object类。

equals ():

如果你只覆盖equals方法,如果a.equals(b)为真,这意味着a和b的hashCode必须是相同的,但这不会发生,因为你没有覆盖hashCode方法。

注意:Object类的hashCode()方法总是为每个对象返回一个新的hashCode。

因此,当您需要在基于哈希的集合中使用对象时,必须重写equals()和hashCode()。

这两个方法都在Object类中定义。两者都是最简单的实现。所以当你需要你想给这些方法添加更多的实现时你就可以在你的类中重写。

对于对象中的equals()方法只检查它在引用上的相等性。如果你也需要比较它的状态,那么你可以像在String类中那样重写它。

Java中的Equals和Hashcode方法

它们是java.lang. object类的方法,object类是所有类(自定义类以及java API中定义的其他类)的超类。

实现:

public boolean equals(对象obj) hashCode()

public boolean equals(对象obj)

这个方法只是检查两个对象引用x和y是否引用同一个对象。例如,它检查x是否== y。

它是自反的:对于任何参考值x, x = (x)应该返回true。

它是对称的:对于任何参考值x和y,当且仅当y = (x)返回true时,x = (y)应该返回true。

它是可传递的:对于任何参考值x、y和z,如果x = (y)返回true, y = (z)返回true,则x = (z)应该返回true。

它是一致的:对于任何参考值x和y, x.equals(y)的多次调用一致返回true或一致返回false,前提是对象上的等号比较中使用的信息没有被修改。

对于任何非空参考值x, x.equals(null)应该返回 假的。

hashCode()

此方法返回调用此方法的对象的哈希码值。此方法以整数形式返回哈希码值,支持基于哈希的集合类,如Hashtable、HashMap、HashSet等。必须在重写equals方法的每个类中重写此方法。

hashCode的一般契约是:

在Java应用程序的执行过程中,只要在同一个对象上多次调用hashCode方法,hashCode方法必须一致地返回相同的整数,前提是该对象上的等号比较中使用的信息没有被修改。

这个整数不需要在应用程序的一次执行和同一应用程序的另一次执行之间保持一致。

如果根据equals(Object)方法,两个对象相等,那么在这两个对象上调用hashCode方法必须产生相同的整数结果。

如果根据equals(java.lang.Object)方法,两个对象是不相等的,那么对每个对象调用hashCode方法必须产生不同的整数结果,这是不要求的。然而,程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。

相等的对象必须产生相同的哈希代码,只要它们是 相等但不相等的对象不需要产生不同的哈希码。

资源:

JavaRanch

图片

在这个回答中没有提到测试equals/hashcode契约。

我发现EqualsVerifier库非常有用和全面。它也很容易使用。

另外,从头构建equals()和hashCode()方法涉及大量样板代码。Apache Commons Lang库提供了EqualsBuilder和HashCodeBuilder类。这些类极大地简化了复杂类的equals()和hashCode()方法的实现。

顺便说一句,值得考虑重写toString()方法以帮助调试。Apache Commons Lang库提供了ToStringBuilder类来帮助实现这一点。

为了帮助你检查重复的对象,我们需要一个自定义的等号和hashCode。

Since hashcode always returns a number its always fast to retrieve an object using a number rather than an alphabetic key. How will it do? Assume we created a new object by passing some value which is already available in some other object. Now the new object will return the same hash value as of another object because the value passed is same. Once the same hash value is returned, JVM will go to the same memory address every time and if in case there are more than one objects present for the same hash value it will use equals() method to identify the correct object.