java HashSet添加相同的列表对象2次

rhfm7lfc  于 2023-05-05  发布在  Java
关注(0)|答案(2)|浏览(185)

我是Java HashSet的新手,在理解以下内容时遇到了问题。在HashSet中,不允许重复的对象,当我们尝试添加重复的对象时,它会给出false作为输出。
然而,当我尝试在HashSet中添加相同的列表对象2次时,它成功地添加了它。
下面是我写的代码。

public class Test{
    public static void main(String[] args) {
        System.out.println(example());
    }

    public static List<List<Integer>> example() {
        Set set = new HashSet();
        List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4));
        set.add(list);
        list.add(33);
        System.out.println(set.add(list));
        return set.stream().toList();
    }

第11行给出true作为输出,而它应该给出false,因为我添加了相同的列表对象

true
[[1, 2, 3, 4, 33], [1, 2, 3, 4, 33]]

Process finished with exit code 0

为什么它的输出是true?

xt0899hw

xt0899hw1#

发生这种情况是因为您在将列表插入到集合中后对其进行了 * 更改 *。一旦你这样做了,集合的行为是未指定的。
正如Set的javadocs中所记录的:
注意:如果可变对象被用作集合元素,则必须非常小心。当对象是集合中的元素时,如果对象的值以影响相等比较的方式更改,则不指定集合的行为。
这是一种过度简化,但可能发生的情况是,当您第一次插入列表时,集合会查看其哈希代码并将其放入相应的桶中。然后再次插入,这次列表有不同的哈希码,所以set将其放入另一个桶中,导致同一个列表被插入两次。
集合的正确行为取决于这样一个事实,即对象一旦被放入集合中就不会改变(以影响equals的方式)。

lmvvr0a8

lmvvr0a82#

HashSet在后台使用HashMap,它使用对象的hashCode来为其查找bucket。向List添加元素后,其hashCode发生了更改,这导致它被标识为不同的对象。
如果你想要引用相等和来自System.identityHashCode的哈希代码,你可以使用IdentityHashMap

Set<List<Integer>> set = Collections.newSetFromMap(new IdentityHashMap<>());

使用此setList将仅添加一次。

相关问题