实现与Set相等

时间:2011-09-27 17:12:48

标签: java equals

我有这堂课:

private static class ClassA{
int id;
String name;

public ClassA(int id, String name){
    this.id= id;
    this.name = name;
}

@Override
public boolean equals(Object o) {
    return ((ClassA)o).name.equals(this.name);
}   

}

如果我在ClassA中覆盖方法等于只比较名称,为什么这个主要打印2个元素?

public static void main(String[] args){
    ClassA myObject = new ClassA(1, "testing 1 2 3");
    ClassA myObject2 = new ClassA(2, "testing 1 2 3");    

    Set<ClassA> set = new HashSet<ClassA>();
    set.add(myObject);
    set.add(myObject2);   
    System.out.println(set.size()); //will print 2, but I want to be 1!
}

如果我查看Set Java documentation

不包含重复元素的集合。更正式地说,集合不包含元素对e1和e2,使得e1.equals(e2)和至多一个null元素。正如其名称所暗示的,该界面对数学集抽象进行建模。

所以显然我只需要覆盖equals,但是我听说我还要覆盖哈希码,但为什么呢?

2 个答案:

答案 0 :(得分:7)

它们具有不同的哈希值,因为您没有覆盖hashCode。这意味着它们被放在HashSet中的两个不同的桶中,因此它们从未与equals首先进行比较。

我会添加

public int hashCode() {
    return name.hashCode();
}

注意id未在hashCode中使用,因为它不用于equals。

(PS我也想指出一个讽刺的是有一个不用于等号的id。这很有趣。通常它是相反的:id是唯一的等于!)

答案 1 :(得分:3)

因为您也没有覆盖hashCode()

  

程序员应注意,任何覆盖Object.equals方法的类都必须覆盖 Object.hashCode方法,以便满足Object.hashCode的一般合同方法。特别是,c1.equals(c2)表示c1.hashCode()==c2.hashCode()

http://download.oracle.com/javase/6/docs/api/java/util/Collection.html

  

hashCode的一般合约是:

     
      
  • 每当在执行Java应用程序期间多次在同一对象上调用它时,hashCode方法必须始终返回相同的整数,前提是不修改对象上的equals比较中使用的信息。从应用程序的一次执行到同一应用程序的另一次执行,该整数不需要保持一致。

  •   
  • 如果两个对象根据equals(Object)方法相等,则对两个对象中的每一个调用hashCode方法必须生成相同的整数结果。

  •   
  • 如果两个对象根据equals(java.lang.Object)方法不相等,则不需要在两个对象中的每一个上调用hashCode方法必须生成不同的整数结果。但是,程序员应该知道为不等对象生成不同的整数结果可能会提高哈希表的性能。

  •   

http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#hashCode()