朋友们,我在HashSets中发现了这样的问题。
public class _235 {
private String s;
public _235(String s){
this.s=s;
}
public static void main(String[] args){
HashSet<Object> hs=new HashSet<Object>();
_235 ws1=new _235("ABC");
_235 ws2=new _235("ABC");
String s1=new String("ABC");
String s2=new String("ABC");
hs.add(ws1);
hs.add(ws2);
hs.add(s1);
hs.add(s2);
System.out.println(hs.size());
}
}
当我检查ws1和ws1都添加到HashSet但没有添加到s1和s2时,只添加了一个String。由于w1和w2没有通过equal(),我相信HashSet并不认为它们是相等的2个对象。但是为什么这对于Strings s1和s2来说也不会变得相同。如何确定它们是有意义的平等对象。请解释一下。
答案 0 :(得分:2)
HashSet
要求您的自定义类覆盖内部用于检测重复元素的equals()
和hashcode()
方法。
String
类有此实现,但您的自定义类_235
没有。
注意:重要的是覆盖equals()
和hashcode()
而不仅仅是其中之一,否则当与基于散列的集合一起使用时,结果可能无法预测。< / p>
您必须覆盖覆盖equals()的每个类中的hashCode()。 如果不这样做将导致违反总承包合同 对于Object.hashCode(),它将阻止您的类运行 正确地与所有基于散列的集合一起使用,包括 HashMap,HashSet和Hashtable。
来自Effective Java的,来自Joshua Bloch
这是link,有很好的解释。
答案 1 :(得分:1)
首先,String重写了它的equals方法,该方法不通过hashCode检查它的内容,所以当你添加String&#34; ABC&#34;的参数时和其他一个&#34; ABC&#34;如果内容相同,它将返回true。
字符串等于方法:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
在对象上,他们只使用默认的equals方法,该方法使用对象的hashCode
对象等于方法:
public boolean equals(Object obj) {
return (this == obj);
}
在你的结果中:
执行equals方法时,wsi
和ws2
将始终返回 false ,因为s1
和{{1}时它们位于不同的内存位置当它们具有相同的内容时会返回 true ,因此只会将s2
添加到one instance
,而HashSet不允许重复。< / p>