Java中复用List导致findDifference方法返回结果异常求助
问题:Java数组求差集结果异常原因分析
需求描述
给定两个0索引整数数组nums1和nums2,需返回大小为2的列表answer:
- answer[0]是nums1中未出现在nums2中的所有不同整数;
- answer[1]是nums2中未出现在nums1中的所有不同整数。
代码实现(含调试打印)
class Solution { public List<List<Integer>> findDifference(int[] nums1, int[] nums2) { Set<Integer> set1 = new HashSet<>(); Set<Integer> set2 = new HashSet<>(); List<List<Integer>> ans = new ArrayList<>(); for(int i : nums2){ set2.add(i); } List<Integer> list = new ArrayList<>(); for(int i : nums1){ set1.add(i); if(!set2.contains(i)) list.add(i); } System.out.println(list); ans.add(list); System.out.println(ans); list.clear(); System.out.println(list); for(int i : nums2){ if(set1.add(i)) { list.add(i); } } System.out.println(list); ans.add(list); System.out.println(ans); return ans; } }
测试输入
nums1 = [1,2,3] nums2 = [2,4,6]
调试输出
[1, 3] [[1, 3]] [] [4, 6] [[4, 6], [4, 6]]
问题
预期ans的最终值为[[1,3],[4,6]],但实际得到[[4, 6], [4, 6]],请问这是什么原因?
原因分析与解决方法
核心问题是复用了同一个List对象list,且在添加到ans后调用了list.clear()。
Java里集合属于引用类型,当你把list添加到ans时,ans存储的是这个list对象的内存引用,而非内容副本。所以后续对list的修改(清空、添加元素)会直接影响ans中已存在的列表:
- 第一次将
[1,3]的list加入ans,此时ans为[[1,3]] - 调用
list.clear()后,list变为空,ans里的第一个元素也会同步变成空列表 - 往空的
list中添加[4,6],此时ans里的两个元素都是同一个list的引用,内容都会变成[4,6],最终就出现了[[4,6],[4,6]]的异常结果。
解决方法
不要复用同一个List对象,处理第二个数组时创建全新的List:
将list.clear()替换为list = new ArrayList<>(),这样第二个列表是独立的新对象,不会影响之前添加到ans中的第一个列表。
修改后的关键代码片段:
ans.add(list); System.out.println(ans); // 替换clear操作,创建新的List对象 list = new ArrayList<>(); System.out.println(list); for(int i : nums2){ // 建议改用!set1.contains(i),逻辑更直观,和需求直接对应 if(!set1.contains(i)) { list.add(i); } }
另外补充:原代码中用set1.add(i)判断元素是否不在nums1中,逻辑是正确的(add返回true表示元素原本不在set1中,即不在nums1里),但换成!set1.contains(i)可读性更强,避免理解混淆。
内容的提问来源于stack exchange,提问作者Vishal Sangole
相关产品推荐
相关产品推荐

