HashSet包含方法,奇怪的行为

这是我的代码:

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 allItems = new HashSet(); allItems.add(new TESTS("a")); allItems.add(new TESTS("a")); System.out.println(allItems.contains(new TESTS("a"))); } } 

我不明白为什么hashset包含方法不会调用我们的规范中提到的equals方法:

更正式地,如果此set不包含元素e,则将指定的元素o添加到此set中(o == null?e == null:o.equals(e))

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

非常感谢您的回答!

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

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

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

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

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

您还应该实现hashCode ,以便它与equals一致。 HashSet使用hashCode方法来决定将项放入哪个存储桶,并且仅当两个项的哈希码相同时才调用equals

Effective Java,2nd Edition第9项中讨论了这个规则(以及破坏它的后果) :覆盖hashCode时总是覆盖hashCode

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

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