【问题标题】:Duplicates in java HashSetjava HashSet中的重复项
【发布时间】:2015-03-31 18:59:37
【问题描述】:

似乎在 HashSet 中允许重复。为什么会这样,我该如何删除它们,为什么第二个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

【问题讨论】:

  • 或者“不可变类的用处”...

标签: java duplicates hashset duplicate-removal


【解决方案1】:

元素在 HashMap 中的存储位置取决于该元素在添加时的hashCode

如果在添加元素后,您更改了导致其 hashCode 更改的该元素的属性(在 ArrayList 元素的情况下,从列表中删除元素正是这样做的),试图在 HashSet 中找到该元素(或删除它)将失败。

【讨论】:

    【解决方案2】:

    散列发生在分桶插入时。如果您之后更改对象,其哈希码将更改,但它已经在其存储桶中。它不会(直接)可检索,因为您将尝试使用与插入它的哈希码不同的哈希码来检索它。

    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
    

    【讨论】:

      【解决方案3】:

      如果您修改 Map 的键或 Set 的元素,您实际上是在破坏它。集合无法知道您已更改元素或正确处理它。

      如果你想修改一个键或元素,你必须先删除它,修改它然后重新添加。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-22
        • 2015-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-28
        相关资源
        最近更新 更多