简体   繁体   English

Java HashSet中的重复项

[英]Duplicates in java HashSet

It seems like duplicates are allowed in HashSets. 似乎HashSets中允许重复。 Why is this, how do I go about removing them, and why doesn't the second remove() work below? 为什么会这样,我该如何删除它们,为什么下面的第二个remove()不起作用? One method of removing all duplicates is new HashSet<>(set) , but is there a better way that doesn't involve creating a new object? 删除所有重复项的一种方法是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);

Output: set consists of two equal, empty lists, and the one that initially wasn't empty can't be removed. 输出: set由两个相等的空列表组成,并且最初不为空的列表无法删除。

2
[[], []]
[[]]
[[]]
[[]]
true

The location an element is stored in the HashMap depends on the hashCode of that element at the time it is added. 元素在HashMap中的存储位置取决于该元素添加时的hashCode

If after adding the element, you change a property of that element that causes its hashCode to change (in the case of an ArrayList element, removing an element from the list does exactly that), trying to find that element in the HashSet (or to remove it) will fail. 如果在添加元素之后,更改了该元素的属性,该属性导致其hashCode发生更改(对于ArrayList元素,则从列表中删除一个元素就可以做到这一点),尝试在HashSet中查找该元素(或删除它)将失败。

Hashing happens at insertion time for bucketing. 散列会在插入时进行存储。 If you change the object afterwards, its hashcode will change, but it will already be in its bucket. 如果之后更改对象,则其哈希码将更改,但已经在其存储桶中。 It will not be (directly) retrievable since you'll be trying to retrieve it with a hashcode different from the one you used to insert it. 由于您将尝试使用与用于插入的哈希码不同的哈希码来检索该哈希码,因此无法(直接)进行检索。

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

If you modify the key of a Map or the element of a Set you are effectively corrupting it. 如果修改Map的键或Set的元素,则实际上是在破坏它。 There is no way for the collection to know you have changed the element, or to handle it correctly. 集合无法知道您已更改元素或正确处理它。

If you want to modify a key or element, you have to first remove it, modify it and add it back in. 如果要修改键或元素,则必须先将其删除,修改并重新添加。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM