Java:hashCode()和equals()的contains,Set方法的协定
本文是关于hashCode的,它等于Set中用于contains(Object o)方法的协定。
关于使用Set中的contains()方法的一个难题
import java.util.HashSet;
class Dog{
String color;
public Dog(String s){
color = s;
} }
public class SetAndHashCode {
public static void main(String[] args) {
HashSet<Dog> dogSet = new HashSet<Dog>();
dogSet.add( new Dog("white"));
dogSet.add( new Dog("white"));
System.out.println("We have " + dogSet.size() + " white dogs!");
if (dogSet.contains( new Dog("white"))){
System.out.println("We have a white dog!");
} else {
System.out.println("No white dog!");
}
}}
输出:
We have 2 white dogs!
No white dog!
我们向集合中添加了两只白狗-dogSet,大小显示我们有2只白狗。但是,为什么在使用contains()方法时没有白狗呢?
Set的contains(Object o)方法
从Java Doc中,当且仅当此集合包含元素e使得(o == null?e == null:o.equals(e))时,contains()方法返回true。因此,contains()方法实际上使用equals()方法检查相等性。
注意,可以将null作为元素添加到集合中。以下代码实际上显示true。
HashSet<Dog> a = new HashSet<Dog>();
a.add( null ); if (a.contains( null )){
System.out.println("true");}
所述公共布尔等于(对象OBJ)方法在对象类中定义。每个类(包括您自己定义的类)都将Object作为超类,并且它是任何类层次结构的根。所有对象(包括数组)都实现此类的方法。
在您自己定义的类中,如果不显式重写此方法,它将具有默认实现。当且仅当两个对象引用同一个对象(即x == y为true)时,它才返回true。
如果将Dog类更改为以下类别,它将起作用吗?
class Dog{
String color;
public Dog(String s){
color = s;
}
//overridden method, has to be exactly the same like the following
public boolean equals(Object obj) {
if (!(obj instanceof Dog))
return false ;
if (obj == this )
return true ;
return this .color.equals(((Dog) obj).color);
}
}
答案是不。
现在问题是由 Java中的hashCode和equals contract 引起的。hashCode()方法是Object类中的另一个方法。
约定是,如果两个对象相等(通过使用equals()方法),则它们必须具有相同的hashCode()。如果两个对象具有相同的哈希码,则它们可能不相等。
public int hashCode()的默认实现为不同的对象返回不同的整数。在此特定示例中,因为我们尚未定义自己的hashCode()方法,所以默认实现将为两个白狗返回两个不同的整数!这违反了合同。
Set中contains()方法的解决方案
class Dog{
String color;
public Dog(String s){
color = s;
}
//overridden method, has to be exactly the same like the following
public boolean equals(Object obj) {
if (!(obj instanceof Dog))
return false ;
if (obj == this )
return true ;
return this .color.equals(((Dog) obj).color);
}
public int hashCode(){
return color.length(); //for simplicity reason
}}