我是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?
2条答案
按热度按时间xt0899hw1#
发生这种情况是因为您在将列表插入到集合中后对其进行了 * 更改 *。一旦你这样做了,集合的行为是未指定的。
正如
Set
的javadocs中所记录的:注意:如果可变对象被用作集合元素,则必须非常小心。当对象是集合中的元素时,如果对象的值以影响相等比较的方式更改,则不指定集合的行为。
这是一种过度简化,但可能发生的情况是,当您第一次插入列表时,集合会查看其哈希代码并将其放入相应的桶中。然后再次插入,这次列表有不同的哈希码,所以set将其放入另一个桶中,导致同一个列表被插入两次。
集合的正确行为取决于这样一个事实,即对象一旦被放入集合中就不会改变(以影响
equals
的方式)。lmvvr0a82#
HashSet
在后台使用HashMap
,它使用对象的hashCode
来为其查找bucket。向List
添加元素后,其hashCode
发生了更改,这导致它被标识为不同的对象。如果你想要引用相等和来自
System.identityHashCode
的哈希代码,你可以使用IdentityHashMap
。使用此
set
,List
将仅添加一次。