更新:答案实际上在文档中:
注意:如果将可变对象用作set,则必须非常小心 元素。如果a的值,则不指定集合的行为 对象以影响等于比较的方式改变 对象是集合中的元素。
结案,谢谢大家!
编辑:关于散列集中重复项的引用主题确实有相同的观点,但是它没有回答我的问题:为什么文档没有说任何关于集合只能保证使用不可变对象?
edit2:我明白会发生什么。该组当然无法知道实体的哈希码何时在添加后发生变化。但重点是,文档应该清楚地说明设置只能与不可变对象一起正常工作。
我已经使用Java工作了5年多了,并且不笑,但直到现在我才意识到集合的一些东西。我以为我理解了一套是什么,即文档说的是什么:
不包含重复元素的集合。更正式的,集合 *不包含
e1
和e2
元素对,*e1.equals(e2)
,最多只有一个null元素。
但是,这完全不正确?!见这里:
public static void main(String[] args) {
Set<Entity> entitySet = new HashSet<>();
Entity e1 = new Entity("One");
Entity e2 = new Entity("Two");
entitySet.add(e1);
entitySet.add(e2);
e2.name = "One"; // !
System.out.println("Objects equal:" + e1.equals(e2));
Iterator<Entity> iterator = entitySet.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
static class Entity {
String name;
Entity(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Entity)) {
return false;
}
return name.equals(((Entity) obj).name);
}
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public String toString() {
return "Entity[name=" + name + "]";
}
输出:
Objects equal:true
Entity[name=One]
Entity[name=One]
所以,我猜关于不包含重复项的集合的事情只有在我们处理不可变条目时才是真的吗?但为什么文件没有说什么呢?我从来没有真正意识到这一点。当然,问题在于,entites可能包含任何不属于等式定义的其他字段;他们在这些领域可能会有所不同。我正在考虑这样的事情:
public static void main(String[] args) {
Set<Entity> entitySet = new HashSet<>();
Entity e1 = new Entity("Public", true);
Entity e2 = new Entity("Secret", false);
entitySet.add(e1);
entitySet.add(e2);
e2.name = "Public";
Iterator<Entity> iterator = entitySet.iterator();
// print only public entity (e1)
while (iterator.hasNext()) {
Entity e = iterator.next();
if (e.equals(e1)) {
System.out.println(e);
}
}
}
static class Entity {
String name;
boolean mayBeDisplayedToUser;
Entity(String name, boolean mayBeDisplayedToUser) {
this.name = name;
this.mayBeDisplayedToUser = mayBeDisplayedToUser;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Entity)) {
return false;
}
return name.equals(((Entity) obj).name);
}
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public String toString() {
return "Entity[name=" + name + ", may be displayed:" + mayBeDisplayedToUser + "]";
}
}
输出:
实体[name = Public,可能会显示:false]实体[name = Public,可能是 显示:真]
所以..我现在很困惑。我是唯一一个不知道这一点的人吗?