HashSets似乎允许重复。为什么会这样,我如何去除它们,为什么第二个remove()
不能在下面工作?删除所有重复项的一种方法是new HashSet<>(set)
,但有没有更好的方法不涉及创建新对象?
Set<ArrayList<String>> set = new HashSet<>();
ArrayList<String> a1 = new ArrayList<>();
ArrayList<String> a2 = new ArrayList<>();
a1.add("a");
set.add(a1);
a1.remove("a");
set.add(a2);
System.out.println(set.size());
System.out.println(set);
ArrayList<String> a3 = new ArrayList<>();
for (Object o : set) {
boolean b = o.equals(a3) && (o.hashCode() == a3.hashCode());
if (!b) System.out.println(false);
}
set.remove(new ArrayList<String>());
System.out.println(set);
set.remove(new ArrayList<String>());
System.out.println(set);
set.remove(set.iterator().next());
System.out.println(set);
System.out.println(set.iterator().next() == a1);
输出:set
由两个相等的空列表组成,最初不为空的列表无法删除。
2
[[], []]
[[]]
[[]]
[[]]
true
答案 0 :(得分:6)
元素存储在HashMap中的位置取决于添加时该元素的hashCode
。
如果在添加元素之后,更改了导致其hashCode更改的元素的属性(在ArrayList元素的情况下,从列表中删除元素就是这样),尝试在HashSet中查找该元素(或删除它)将失败。
答案 1 :(得分:3)
哈希在插入时发生了分组。如果之后更改了对象,其哈希码将会更改,但它已经在其存储桶中。它不会(直接)可检索,因为您将尝试使用与您用于插入它的哈希码不同的哈希码来检索它。
a1.add("a");
set.add(a1); // hashed and bucketed
a1.remove("a"); // hash code changes but doesn't affect set
set.add(a2); // hashes to a different place than a1
答案 2 :(得分:1)
如果修改Map的键或Set的元素,则实际上是在破坏它。集合无法知道您已更改元素或正确处理它。
如果要修改键或元素,则必须先将其删除,修改并重新添加。