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。 执行此操作的规范方式如下所示(假设first
和last
不能为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
类,它不知道你的last
和first
变量。
我希望它有所帮助。
你的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
您还可以看到代码的执行方式。
-
当您尝试在集合中添加元素时,它会调用哈希代码并获取存储桶。
-
从哈希码中获取哈希值后,将为所有具有相同哈希令牌的人运行覆盖的等号。
希望这可以帮助。