繁体   English   中英

HashSet允许重复

[英]HashSet allows duplicates

我似乎无法使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$

您需要重写equals(Object) 而不是这样做,您实现了带有签名equals(Subclass)equals方法。 因此你HashSet使用的是默认equals(Object)方法定义Object平等的测试。

默认的equals(Object)实现基于对象标识,因此该集合“允许”您添加两个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; } 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) {
    ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM