【问题标题】:Why is the size of this set 1 after adding 5 objects?为什么添加 5 个对象后这个集合的大小为 1?
【发布时间】:2019-03-28 12:36:35
【问题描述】:

我试图弄清楚为什么这段代码会输出 1:

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

public class Test {
    public static void main(String[] args) {
        Set<Foo> myFooSet= new HashSet<Foo>(); 
        myFooSet.add(new Foo(2));
        myFooSet.add(new Foo(1));
        myFooSet.add(new Foo(3));
        myFooSet.add(new Foo(3));
        myFooSet.add(new Foo(2));
        System.out.print(myFooSet.size());
    }
}
class Foo {
     Integer code;
     Foo(Integer c) {
         code= c;
     }
     public boolean equals(Foo f) {
         return false;
     }
     public boolean equals(Object f) {
         return true;
     }
     public int hashCode() {
         return 17;
     }
}

【问题讨论】:

  • 因为哈希码相同并且equals返回true,所以所有5个元素都被认为是相等的并相互替换(你肯定知道集合不允许重复)。阅读equals()hashCode() 了解更多信息。
  • @Thomas 实际上它们不会互相替换。仅添加第一个元素。
  • @Eran 是的,你是对的。我应该重新阅读 JavaDoc(“如果该集合已经包含该元素,则调用将保持集合不变并返回 false。”)-d'oh.
  • 可能表明我们永远不应忽视add(和其他类似方法)返回的值...

标签: java hashmap hashset


【解决方案1】:

您在Foo 类中定义的public boolean equals(Object f)public int hashCode() 方法基本上说所有Foo 实例彼此相等,因此只能将Foo 的一个实例添加到任何HashSet

因此,myFooSet.size() 将返回 1,无论您尝试添加多少个 Foo 元素(只要您至少添加了一个)。

注意:HashSet 永远不会使用您的 public boolean equals(Foo f) 方法,因为 HashSet 仅使用在 Object 类 - public boolean equals(Object obj) 中声明的 equals 方法 - 您覆盖它以始终返回 true

【讨论】:

  • 另一个需要明确的重要细节是永远不会调用equals(Foo) 重载,因为HashMap 无法知道它的存在,所以equals(Object) 是被调用的重载。所以虽然new Foo(1).equals(new Foo(1)) 是假的,但它从未真正使用过。
【解决方案2】:

添加到@Eran 答案,定义equals(Foo f) 方法不会覆盖比较时使用的Object.equals(java.lang.Object) 方法,即使您的对象是Foo

public boolean equals(Foo f) {

在您的代码中没有调用

【讨论】:

    猜你喜欢
    • 2013-02-20
    • 2013-02-19
    • 1970-01-01
    • 1970-01-01
    • 2016-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多