HashSet允许重复

发布于 2024-08-09 22:34:38 字数 1498 浏览 4 评论 0原文

我似乎无法让 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());
    }
  }
}

Subclass

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$

I can't seem to get a HashSet instance to work as expected. The code I used is as follows:

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());
    }
  }
}

Subclass

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();
  }
}

This code outputs

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$

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

木落 2024-08-16 22:34:38

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

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

You need to override equals(Object). Instead of doing this you've implemented an equals method with signature equals(Subclass). Consequently your HashSet is using the default equals(Object) method defined on Object for equality testing.

The default equals(Object) implementation is based on object identity, and hence the set "allows" you to add two Strings that, whilst semantically equal, are not the same object.

奢欲 2024-08-16 22:34:38

您没有正确重写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) 创建了第二个方法,这不是您想要做的。

You did not correctly override Object.equals().

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

The method boolean equals(Subclass other) creates a second method which is not what you intended to do.

孤者何惧 2024-08-16 22:34:38

两个元点:

首先,养成每次您认为要重写方法时都使用 @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 ) { 返回真; } 但养成习惯确实不值得。

Two meta-points:

First, get in the habit of using @Override every time you believe you are overriding a method. That would have caused your example code to fail to compile, leading you to discover the problem.

Second, if you're using an IDE, and it didn't highlight a nice bold warning for you, it is misconfigured! You should fix it!

And if you're not using an IDE -- you really, really should be. As soon as you typed public boolean equals(Subclass other), the text would change color and a warning would be displayed telling you what your likely problem is.

Incidentally, the standard idiom for equals() that I've converged on is this:

@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;
}

In some cases, it is worth prepending an if (object == this) { return true; } but it's really not worthwhile to make a regular habit of it.

桃扇骨 2024-08-16 22:34:38

我遇到了几乎同样的问题,正如每个人都说的那样,您需要重写正确的 public boolean equals(Object o) 方法。但这还不够!

还需要覆盖 public int hashCode() (就像你所做的那样),否则,java根本不会调用 equals 方法。

I had almost the same problem, as everyone said you need to override the right public boolean equals(Object o) method. But that's not enough!

It is also necessary to override public int hashCode() (as you did), otherwise, java wouldn't call the equals method at all.

浅笑轻吟梦一曲 2024-08-16 22:34:38

首先猜测,您的 equals(Subclass other) 应该是 equals(Object other) 才能覆盖 java.lang.Object.equals( ) 方法,如你所愿。该集合可能正在调用底层的 equals() 实现。

First guess, it looks like your equals(Subclass other) ought to be equals(Object other) in order to override the java.lang.Object.equals() method, as you want. Probably the set is calling the underlying equals() implementation.

黎夕旧梦 2024-08-16 22:34:38

您的 equals 方法永远不会被调用。 equals 的签名要求它采用 Object,而不是其他类(包括恰好实现 equals 的任何类)。

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

Your equals method is never called. The signature of equals requires that it take an Object, not some other class (including whatever class happens to be implementing equals).

public boolean equals(Object other) {
    ...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文