HashSet允许重复

时间:2009-11-02 20:31:55

标签: java duplicates hashset

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

import testing.Subclass;
import java.util.HashSet;

public class tester {
  public static void main(String[] args) throws Exception {
    HashSet<Subclass> set = new HashSet<Subclass>();
    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<Subclass> {

  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$

6 个答案:

答案 0 :(得分:20)

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

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

答案 1 :(得分:5)

您没有正确覆盖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)创建了第二种方法,而不是您打算做的。

答案 2 :(得分:3)

两个要点:

首先,每当你认为自己重写方法时,养成使用@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; },但实际上习惯它是不值得的。

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

永远不会调用你的equals方法。 equals的签名要求它需要Object,而不是其他类(包括正在实现equals的任何类)。

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