vap*_*p78 4 java collections hashset
根据java.util.HashSet.contains()的JavaDoc,该方法执行以下操作
如果此set包含指定的元素,则返回true.更正式地,当且仅当此集合包含元素e时才返回true (o == null?e == null:o.equals(e)).
但是,这似乎不适用于以下代码:
public static void main(String[] args) {
HashSet<DemoClass> set = new HashSet<DemoClass>();
DemoClass toInsert = new DemoClass();
toInsert.v1 = "test1";
toInsert.v2 = "test2";
set.add(toInsert);
toInsert.v1 = null;
DemoClass toCheck = new DemoClass();
toCheck.v1 = null;
toCheck.v2 = "test2";
System.out.println(set.contains(toCheck));
System.out.println(toCheck.equals(toInsert));
}
private static class DemoClass {
String v1;
String v2;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((v1 == null) ? 0 : v1.hashCode());
result = prime * result + ((v2 == null) ? 0 : v2.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DemoClass other = (DemoClass) obj;
if (v1 == null) {
if (other.v1 != null)
return false;
} else if (!v1.equals(other.v1))
return false;
if (v2 == null) {
if (other.v2 != null)
return false;
} else if (!v2.equals(other.v2))
return false;
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
打印出来:
假
真正
所以虽然equals
方法返回true
,但HashSet.contains()
返回false
.
我想这是因为我在将它添加到集合后修改了toInsert实例.
然而,这绝不是文件记录(或者至少我无法找到).此外,应使用上面引用的equals方法文档,但似乎并非如此.
当一个对象被存储在一个HashSet
数据结构中时,该数据结构很容易(读取:有效地)被对象搜索hashCode()
.修改对象可能会改变它hashCode()
(取决于你如何实现它),但不会更新它的位置HashSet
,因为对象无法知道它包含在一个对象中.
你可以在这里做几件事:
修改实现,hashCode()
使其不受您正在更改的字段的影响.假设这个字段对于对象的状态很重要,并且参与该equals(Object)
方法,这有点像代码味道,应该可以避免.
在修改对象之前,将其从集合中删除,然后在完成修改后重新添加它:
Set<DemoClass> mySet = ...;
DemoClass demo = ...;
boolean wasInSet = mySet.remove(demo);
demo.setV1("new v1");
demo.setV2("new v2");
if (wasInSet) {
set.add(demo);
}
Run Code Online (Sandbox Code Playgroud)