HashSet允许重复

我似乎无法让HashSet实例按预期工作。 我使用的代码如下:

 import testing.Subclass; import java.util.HashSet; public class tester { public static void main(String[] args) throws Exception { HashSet set = new HashSet(); set.add(new Subclass("007812")); set.add(new Subclass("007813")); System.out.println("Set size " + set.size()); set.add(new Subclass("007812")); System.out.println("Set size " + set.size()); for(Subclass sub : set) { System.out.println(" sub acctNbr " + sub.getAcctNbr()); } } } 

子类

 public class Subclass implements Comparable { public Subclass(String acctNbr) { this.acctNbr = acctNbr; } private String acctNbr; public String getAcctNbr() { return this.acctNbr; } public int compareTo(Subclass other) { return this.getAcctNbr().compareTo(other.getAcctNbr()); } public boolean equals(Subclass other) { if(other.getAcctNbr().equals(this.getAcctNbr())) return true; else return false; } public int hashCode() { return acctNbr.hashCode(); } } 

此代码输出

 sross@sross-workstation:~/Documents$ javac testing/Subclass.java sross@sross-workstation:~/Documents$ javac tester.java sross@sross-workstation:~/Documents$ java tester Set size 2 Set size 3 sub acctNbr 007812 sub acctNbr 007812 sub acctNbr 007813 sross@sross-workstation:~/Documents$ 

您需要覆盖equals(Object) 。 你没有这样做,而是实现了一个带有签名equals(Subclass)equals方法。 因此,您的HashSet使用equals(Object)定义的默认equals(Object)方法进行相等性测试。

默认的equals(Object)实现基于对象标识,因此set“允许”添加两个String ,虽然在语义上相同,但它们不是同一个对象。

您没有正确覆盖Object.equals()

 @Override public boolean equals(Object other) { if ((other == null) || !(other instanceof Subclass)) { return false; } return ((Sublcass) other).getAcctNbr().equals(this.getAcctNbr()); } 

boolean equals(Subclass other)方法创建了第二个方法,而不是您打算做的。

两个要点:

首先,每当您认为自己重写方法时,养成使用@Override的习惯。 这会导致您的示例代码无法编译,导致您发现问题。

其次,如果您正在使用IDE,并且它没有为您突出显示一个很好的大胆警告,则它配置错误! 你应该解决它!

如果你没有使用IDE – 你真的,真的应该。 一旦键入public boolean equals(Subclass other) ,文本就会改变颜色,并会显示一条警告,告诉您可能出现的问题。

顺便说一下,我收集的equals()的标准习惯是:

 @Override public boolean equals(Object object) { if (object instanceof Subclass) { Subclass that = (Subclass) object; return this.anInt == that.anInt && this.aString.equals(that.aString); // for example } return false; } 

某些情况下,值得添加一个if (object == this) { return true; } 但是,养成它的习惯是不值得的。

我有几乎相同的问题,因为每个人都说你需要覆盖正确的public boolean equals(Object o)方法。 但这还不够!

还必须覆盖public int hashCode() (就像你一样),否则,java根本不会调用equals方法。

首先猜测,看起来你的equals(Subclass other)应该是equals(Object other) ,以便根据需要覆盖java.lang.Object.equals()方法。 该集合可能正在调用底层的equals()实现。

永远不会调用你的equals方法。 equals的签名要求它接受一个Object ,而不是其他一些类(包括碰巧实现equals任何类)。

 public boolean equals(Object other) { ... }