如何能够做到以下几点:
void contains(LinkedHashSet data, Object arg) {
System.out.println(data.getClass()); // java.util.LinkedHashSet
System.out.println(arg.hashCode() == data.iterator().next().hashCode()); // true
System.out.println(arg.equals(data.iterator().next())); // true
System.out.println(new ArrayList(data).contains(arg)); // true
System.out.println(new HashSet(data).contains(arg)); // true
System.out.println(new LinkedHashSet(data).contains(arg)); // true (!)
System.out.println(data.contains(arg)); // false
}我做错了什么吗?
显然,这种情况并不总是发生(如果您创建了一组琐碎的对象,就不会再现它)。但在我的情况下,这种情况总是发生在更复杂的arg类中。
编辑:我没有在这里定义arg的主要原因是它是相当大的类,Eclipse生成的hashCode跨越20行,equals的长度是它的两倍。我不认为这是相关的,只要它们对这两个物体是相等的。
发布于 2011-11-04 10:42:21
当您构建自己的对象并计划在集合中使用它们时,您应该始终覆盖以下方法:
boolean equals(Object o);
int hashCode();equals的默认实现检查对象是否指向同一个对象,而您可能希望重新定义它以检查内容。
根据合理的实际情况,类对象定义的hashCode方法确实返回不同对象的不同整数。要遵守规则,对象的hashCode与另一个对象的规则应该是相同的,因此您还必须重新定义hashCode。
编辑:我原以为会有错误的hashCode或equals实现,但自从您的回答之后,您就发现在将密钥添加到HashSet或HashMap之后,您正在对它们进行变异。
将对象添加到散列集合时,将计算其hashCode并将其映射到集合中的物理位置。
如果一些用于计算hashCode的字段被更改,那么hashCode本身就会改变,因此HashSet实现将变得混乱。当它试图获取对象时,它将查看另一个物理位置,而不会找到该对象。但是,如果枚举集合,则该对象仍然存在。
出于这个原因,请始终使HashMap或HashSet键。
发布于 2011-11-04 11:18:34
明白了。一旦你知道了,答案是如此明显,你只能在尴尬中脸红。
static class MyObj {
String s = "";
@Override
public int hashCode() {
return s.hashCode();
}
@Override
public boolean equals(Object obj) {
return ((MyObj) obj).s.equals(s);
}
}
public static void main(String[] args) {
LinkedHashSet set = new LinkedHashSet();
MyObj obj = new MyObj();
set.add(obj);
obj.s = "a-ha!";
contains(set, obj);
}这就足以可靠地复制它了。
说明:Thou从不修改用于hashCode()!的字段
发布于 2011-11-04 10:31:59
你的问题好像漏掉了什么。我做了一些猜测:
private void testContains() {
LinkedHashSet set = new LinkedHashSet();
String hello = "Hello!";
set.add(hello);
contains(set, hello);
}
void contains(LinkedHashSet data, Object arg) {
System.out.println(data.getClass()); // java.util.LinkedHashSet
System.out.println(arg.hashCode() == data.iterator().next().hashCode()); // true
System.out.println(arg.equals(data.iterator().next())); // true
System.out.println(new ArrayList(data).contains(arg)); // true
System.out.println(new HashSet(data).contains(arg)); // true
System.out.println(new LinkedHashSet(data).contains(arg)); // true (!)
System.out.println(data.contains(arg)); // true (!!)
}编辑:跟踪不断变化的问题!
除了第一次输出之外,我仍然得到了“真”。请更具体地说明"arg“参数的类型。
https://stackoverflow.com/questions/8007723
复制相似问题