18

如果我运行以下代码,则输出为 2,这意味着该集合包含 2 个元素。但是我认为该集合应该包含 1,因为这两个对象基于hashcode()值和.equals()方法是相等的。在我的理解中似乎有一些明显的错误?

package HELLO;

import java.util.HashSet;
import java.util.Set;

public class Test {

    public static void main(String[] args) throws Exception {
        Set<Alpha> s = new HashSet<Alpha>();
        Alpha a1 = new Alpha();
        Alpha a2 = new Alpha();
        s.add(a1);
        s.add(a2);
        System.out.println(s.size());
    }
}   

class Alpha {
    int a = 10;

    public int hashcode() {
        return a;
    }

    public boolean equals(Object obj) {
        return (obj instanceof Alpha && ((Alpha) obj).a == this.a);
    }

    public String toString() {
        return "Alpha : " + a;
    }
}
4

3 回答 3

34

您的哈希代码方法不会覆盖 Object 类的哈希代码方法,因此您的 equals 方法会违反合同,因为它与 hashCode 结果不一致,并且您可以拥有“相等”但具有不同 hashCode 的对象。

请记住:在覆盖方法时,您应该始终使用@Override注解,因为这将帮助您捕获此错误和类似错误。

@Override  // ** don't forget this annotation
public int hashCode() { // *** note capitalization of the "C"
  return a;
}

此外,您还需要改进代码格式,尤其是在此处发布代码供我们审核时。如果它符合标准,我们将能够更好地理解您的代码并为您提供帮助(这就是存在标准的原因)。所以尽量保持你的缩进与同一块中的所有代码行在同一级别缩进一致,并且你需要确保基本级别的代码,包括导入、外部类声明和它的结束大括号,是齐平的:

import java.util.HashSet;
import java.util.Set;

public class Test {

   public static void main(String[] args) throws Exception {
      Set<Alpha> s = new HashSet<Alpha>();
      Alpha a1 = new Alpha();
      Alpha a2 = new Alpha();
      s.add(a1);
      s.add(a2);
      System.out.println(s.size());
   }
}

class Alpha {
   int a = 10;

   @Override
   public int hashCode() {
      return a;
   }

   public String toString() {
      return "Alpha : " + a;
   }

   @Override
   public boolean equals(Object obj) {
      if (this == obj)
         return true;
      if (obj == null)
         return false;
      if (getClass() != obj.getClass())
         return false;
      Alpha other = (Alpha) obj;
      if (a != other.a)
         return false;
      return true;
   }
}

有关这方面的精彩评论,请阅读:Overriding equals and hashCode in Java

于 2013-05-09T13:12:05.323 回答
4

@Overrides 注解是覆盖超类中的同名方法”。

@Override
public int hashCode() {
    return a;
}

@Override
public boolean equals(Object obj) {
    return (obj instanceof Alpha && ((Alpha) obj).a == this.a);

}

@Override
public String toString() {
    return "Alpha : " + a;
}
于 2013-05-09T13:14:10.887 回答
4

您的方法哈希码应命名为hashCode(大写字母“C”)。

如果您计划覆盖方法,则应使用@Override注释。

如果您使用了该注释,您会更早注意到这个问题,因为代码不会编译。

于 2013-05-09T13:14:54.427 回答