HashSet包含()方法

我执行下面的代码,发现输出是false

 import java.util.Set; import java.util.HashSet; public class Name { private String first, last; public Name(String first, String last) { this.first = first; this.last = last; } public boolean equals(Object o) { if (!(o instanceof Name)) return false; Name n = (Name) o; return n.first.equals(first) && n.last.equals(last); } public static void main(String[] args) { Set s = new HashSet(); s.add(new Name("Donald", "Duck")); System.out.println(s.contains(new Name("Donald", "Duck"))); } } 

我想知道它的行为以及为什么输出是false

您还需要覆盖hashCode()方法以及equals() 。 这两个方法都用于HashSet正常function,因此如果要将class作为key ,则必须在用户定义的类中重写,否则将使用Object类的hashCode() ,并且不能将两个不同的objects视为与hashCode()一样,它们总是不同的,并且在contains()的情况下肯定会返回false

为了使HashSet (或HashMap ,就此问题)正确定位您的对象,您需要覆盖hashCode()方法,以便两个相等的对象具有相同的hashCode。 执行此操作的规范方式如下所示(假设firstlast不能为null ,就像您的equals方法假设:

 @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + first.hashCode(); result = prime * result + last.hashCode(); } 

Java中任何基于Hash的数据结构实现(集合)都基于两件事来检查重复:

1:如果equals方法对已存储在集合中的任何元素返回true

2:如果hashCode方法为已存储在集合中的任何元素返回same integer value

所以在你的情况下你没有重写hashCode方法,这意味着它将尝试使用hashCode方法检查hashCode相等性,默认实现Object类,它不知道你的lastfirst变量。

我希望它有所帮助。

你的equals()方法没问题,但你错过了覆盖hashCode()方法,只是覆盖hashCode()方法,它会工作。 并且不要忘记你总是需要覆盖equals() and hashCode()或者都不需要覆盖它们以获得正确的行为。 如果您计划将对象用作散列机制中的键,则必须覆盖它们。

 @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((first == null) ? 0 : first.hashCode()); result = prime * result + ((last == null) ? 0 : last.hashCode()); return result; } 

您必须覆盖覆盖hashCode()的每个类中的hashCode() equals() 如果不这样做,将导致违反Object.hashCode()的常规合同,这将阻止您的类与所有基于散列的集合(包括HashMap, HashSet, and Hashtable一起正常运行。

来自Effective Java,来自Joshua Bloch

您还可以看到代码的执行方式。

  1. 当您尝试在集合中添加元素时,它会调用哈希代码并获取存储桶。

  2. 从哈希码中获取哈希值后,将为所有具有相同哈希令牌的人运行覆盖的等号。

希望这可以帮助。