为何向Java HashSet重复添加同一List对象会返回true?
为什么向HashSet两次添加同一个List对象会成功?
先看你给出的代码:
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(); } }
核心原因是HashSet判断元素重复的逻辑依赖对象的hashCode()和equals(),而你修改List后它的hashCode()发生了变化,导致HashSet无法识别这是同一个对象。
具体执行流程:
- 第一次调用
set.add(list)时,HashSet会计算此时List的hashCode()(基于初始元素[1,2,3,4]生成),并把这个List对象存入对应的哈希桶中。 - 调用
list.add(33)修改List内容后,ArrayList的hashCode()会重新计算(因为它的哈希值是基于内部所有元素生成的,元素改变哈希值必然改变)。 - 第二次调用
set.add(list)时,HashSet会用修改后的hashCode()定位哈希桶,这个桶和第一次的桶不是同一个,而且是空的。HashSet只会检查当前定位到的桶,不会遍历所有桶,所以它找不到已经存在的同一个List对象,于是就把这个List再次添加进去,返回true。
你看到的输出[[1,2,3,4,33],[1,2,3,4,33]],本质是HashSet里存储了同一个List对象的两次引用,输出时显示的是该List当前的内容(已经被修改为包含33)。
注意:永远不要修改已经存入HashSet、HashMap这类哈希集合中的对象内容,这会破坏集合的内部结构,引发重复元素、查找失效等难以排查的问题。
内容的提问来源于stack exchange,提问作者Manav Sidana
相关产品推荐
相关产品推荐

