HashSet contains() 方法
HashSet contains() method
我执行了下面的代码,发现输出是 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
。
您还需要覆盖 hashCode()
方法以及 equals()
。这两种方法都用于 HashSet
的正常功能,因此如果您将 class
作为a key
, else hashCode()
of Object
class 正在被使用,没有两个不同的 objects
可以被认为与他们的 hashCode()
总是一样会有所不同,并且肯定会 return false
总是 contains()
。
为了让 HashSet
(或 HashMap
,就此而言)正确定位您的对象,您需要覆盖 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();
}
你的equals()
方法没问题,但是你错过了覆盖hashCode()
方法,直接覆盖hashCode()
方法就可以了。并且不要忘记您总是需要覆盖它们的 equals() and hashCode()
或 none 以获得正确的行为。如果您打算将您的对象用作哈希机制中的键,那么您必须覆盖它们。
@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;
}
您必须在覆盖 equals()
的每个 class 中覆盖 hashCode()
。不这样做将导致违反 Object.hashCode()
的一般合同,这将阻止您的 class 与所有基于散列的集合一起正常运行,包括 HashMap, HashSet, and Hashtable
.
来自 Effective Java,作者:Joshua Bloch
Java 中任何基于 Hash
的数据结构实现(集合)基于两件事检查重复:
1 : if equals
方法 returns true
对于已经存储在集合中的任何元素。
2 : 如果 hashCode
方法 returns same integer value
用于已存储在集合中的任何元素。
所以在你的情况下你没有覆盖 hashCode 方法,这意味着它会尝试使用 hashCode 方法默认实现 Object
class 检查 hashCode 相等性,它不知道你的 last
和 first
变量。
希望对您有所帮助。
您还可以看到您的代码将如何执行。
当您尝试在集合中添加元素时,它会调用哈希码并获取存储桶。
一旦您从散列码中获得散列值,对于所有具有相同散列令牌的人,覆盖的等于将是 运行。
希望对您有所帮助。
我执行了下面的代码,发现输出是 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
。
您还需要覆盖 hashCode()
方法以及 equals()
。这两种方法都用于 HashSet
的正常功能,因此如果您将 class
作为a key
, else hashCode()
of Object
class 正在被使用,没有两个不同的 objects
可以被认为与他们的 hashCode()
总是一样会有所不同,并且肯定会 return false
总是 contains()
。
为了让 HashSet
(或 HashMap
,就此而言)正确定位您的对象,您需要覆盖 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();
}
你的equals()
方法没问题,但是你错过了覆盖hashCode()
方法,直接覆盖hashCode()
方法就可以了。并且不要忘记您总是需要覆盖它们的 equals() and hashCode()
或 none 以获得正确的行为。如果您打算将您的对象用作哈希机制中的键,那么您必须覆盖它们。
@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;
}
您必须在覆盖 equals()
的每个 class 中覆盖 hashCode()
。不这样做将导致违反 Object.hashCode()
的一般合同,这将阻止您的 class 与所有基于散列的集合一起正常运行,包括 HashMap, HashSet, and Hashtable
.
来自 Effective Java,作者:Joshua Bloch
Java 中任何基于 Hash
的数据结构实现(集合)基于两件事检查重复:
1 : if equals
方法 returns true
对于已经存储在集合中的任何元素。
2 : 如果 hashCode
方法 returns same integer value
用于已存储在集合中的任何元素。
所以在你的情况下你没有覆盖 hashCode 方法,这意味着它会尝试使用 hashCode 方法默认实现 Object
class 检查 hashCode 相等性,它不知道你的 last
和 first
变量。
希望对您有所帮助。
您还可以看到您的代码将如何执行。
当您尝试在集合中添加元素时,它会调用哈希码并获取存储桶。
一旦您从散列码中获得散列值,对于所有具有相同散列令牌的人,覆盖的等于将是 运行。
希望对您有所帮助。