最近我读了这篇文章 开发人员工作文件。
该文档是关于有效和正确地定义hashCode()和equals(),但我无法弄清楚为什么我们需要覆盖这两个方法。
我如何决定有效地实现这些方法?
最近我读了这篇文章 开发人员工作文件。
该文档是关于有效和正确地定义hashCode()和equals(),但我无法弄清楚为什么我们需要覆盖这两个方法。
我如何决定有效地实现这些方法?
当前回答
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
图片
其他回答
考虑在一个桶中收集所有黑色的球。你的工作是像下面这样给这些球上色,并将其用于适当的游戏,
对于网球-黄色,红色。 板球-白色
现在水桶有三种颜色的球黄色,红色和白色。只有你知道哪个颜色适合哪个游戏。
给球上色-哈希。 选择比赛的球-平等。
如果你给球上色,然后有人选了板球或网球,他们不会介意颜色的!!
它在使用值对象时很有用。以下摘自Portland Pattern Repository:
Examples of value objects are things like numbers, dates, monies and strings. Usually, they are small objects which are used quite widely. Their identity is based on their state rather than on their object identity. This way, you can have multiple copies of the same conceptual value object. So I can have multiple copies of an object that represents the date 16 Jan 1998. Any of these copies will be equal to each other. For a small object such as this, it is often easier to create new ones and move them around rather than rely on a single object to represent the date. A value object should always override .equals() in Java (or = in Smalltalk). (Remember to override .hashCode() as well.)
常见错误如下例所示。
public class Car {
private String color;
public Car(String color) {
this.color = color;
}
public boolean equals(Object obj) {
if(obj==null) return false;
if (!(obj instanceof Car))
return false;
if (obj == this)
return true;
return this.color.equals(((Car) obj).color);
}
public static void main(String[] args) {
Car a1 = new Car("green");
Car a2 = new Car("red");
//hashMap stores Car type and its quantity
HashMap<Car, Integer> m = new HashMap<Car, Integer>();
m.put(a1, 10);
m.put(a2, 20);
System.out.println(m.get(new Car("green")));
}
}
绿色的车没有找到
2. hashCode()引起的问题
该问题是由未覆盖的hashCode()方法引起的。equals()和hashCode()之间的契约是:
如果两个对象相等,那么它们必须具有相同的哈希码。 如果两个对象具有相同的哈希码,则它们可能相等,也可能不相等。 公共int hashCode(){ 返回this.color.hashCode (); }
你必须重写hashCode()在每个 重写equals()的类。失败 这样做会导致违反 总合同 Object.hashCode(),它将防止 你的类不能正常运行 结合所有基于哈希的 集合,包括HashMap, HashSet和Hashtable。 摘自Joshua Bloch的《Effective Java》
通过一致地定义equals()和hashCode(),可以提高类作为基于散列的集合中的键的可用性。正如hashCode的API文档所解释的那样:“支持此方法是为了受益于诸如java.util.Hashtable所提供的哈希表。”
关于如何有效地实现这些方法的问题,最好的答案是建议你阅读《Effective Java》的第3章。
hashCode ():
如果只重写hash-code方法,什么也不会发生,因为它总是为每个对象返回一个新的hashCode作为object类。
equals ():
如果你只覆盖equals方法,如果a.equals(b)为真,这意味着a和b的hashCode必须是相同的,但这不会发生,因为你没有覆盖hashCode方法。
注意:Object类的hashCode()方法总是为每个对象返回一个新的hashCode。
因此,当您需要在基于哈希的集合中使用对象时,必须重写equals()和hashCode()。