HashSet包含方法,奇怪的行为

时间:2011-03-31 19:56:58

标签: java

这是我的代码:

public class testGui {



    public static void main(String[] arg){
        class TESTS{
            String t;

            public TESTS(String t){
                this.t = t;
            }

            @Override
            public boolean equals(Object x){
                System.out.println("My method is called...");
                if(x instanceof TESTS){
                    TESTS zzz = (TESTS) x;
                    return zzz.t.compareTo(t)==0;
                }
                else return false;
            }
        }
        HashSet<TESTS> allItems = new HashSet<TESTS>();
        allItems.add(new TESTS("a"));
        allItems.add(new TESTS("a"));
        System.out.println(allItems.contains(new TESTS("a")));
    }

}

我不明白为什么hashset contains方法没有调用我们的规范中提到的equals方法:

  

更正式地说,添加指定的   如果此设置,则为此集合的元素o   不包含元素e   (o == null?e == null:o.equals(e))

我的代码返回false而不是进入我的equals方法。

非常感谢您的回答!

4 个答案:

答案 0 :(得分:13)

覆盖equals时,您还必须覆盖hashCode。否则,相等的对象将具有不同的哈希码并被视为不相等。

强烈建议不要仅覆盖 hashCode。但这并不重要,因为不等的对象可以具有相同的哈希码。

答案 1 :(得分:7)

HashSet取决于每个对象的HashCode。在调用equals方法之前,将调用hashCode方法。如果哈希码相等,则hashset认为值得评估equals方法。

实现一个哈希码方法,如果a.equals(b)== true,那么a.hashCode()== b.hashCode()

它应该像你期望的那样开始工作。

答案 2 :(得分:3)

您还应该实施hashCode,以便与equals保持一致。 HashSet使用hashCode方法决定将项目放入哪个存储区,并仅在两个项目的哈希码相同时调用equals

Effective Java,2nd Edition 第9项:覆盖hashCode equals,讨论此规则(以及破解它的后果)强>

答案 3 :(得分:0)

由于大多数评论都是......只是覆盖哈希码方法(下面的示例),你应该很好。

@Override
        public int hashCode() {
            return t.hashCode()*31;
        }