我执行了下面的代码,发现输出为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<Name> s = new HashSet<Name>();
s.add(new Name("Donald", "Duck"));
System.out.println(s.contains(new Name("Donald", "Duck")));
}
}
我想知道它的行为方式以及输出为false
的原因。
答案 0 :(得分:5)
您还需要覆盖hashCode()
方法以及equals()
。这两种方法都用于HashSet
的正常功能,因此如果您将class
作为key
,则必须在用户定义的类中覆盖, hashCode()
类的其他Object
被使用,并且没有两个不同的objects
被视为与hashCode()
总是不同的false
相同,并且肯定会返回{{1}总是在contains()
。
答案 1 :(得分:3)
为了使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();
}
答案 2 :(得分:2)
Java中基于Hash
的任何数据结构实现(集合)都基于两件事检查重复:
1:如果equals
方法为已存储在集合中的任何元素返回true
。
2:如果hashCode
方法为已存储在集合中的任何元素返回same integer value
。
所以在你的情况下你没有覆盖hashCode方法,这意味着它将尝试使用hashCode方法检查hashCode相等性Object
类的默认实现,它不知道你的last
和first
变量。
我希望它有所帮助。
答案 3 :(得分:1)
您的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;
}
答案 4 :(得分:1)
您必须在覆盖hashCode()
的每个类中覆盖equals()
。如果不这样做,将导致违反Object.hashCode()
的一般合同,这将阻止您的课程与所有基于散列的集合(包括HashMap, HashSet, and Hashtable
)一起正常运行。
,来自Joshua Bloch
答案 5 :(得分:0)
您还可以查看代码的执行方式。
当您尝试在集合中添加元素时,它会调用哈希码并获取存储桶。
从哈希码中获取哈希值后,将为所有具有相同哈希令牌的人运行覆盖的等号。
希望这有帮助。