Java如何移除主列表内的重复嵌套子列表并修复代码报错
Java嵌套List子列表去重实现方案
原代码问题排查
你写的代码运行报错、结果不符合预期,核心原因有3个:
- 遍历删除的索引逻辑错误:在内层循环直接调用
remove(n)删除元素后,列表长度会立刻缩短,后续元素会向前移位,但循环变量n还是照常自增,既会漏判移位过来的元素,还会因为n超过当前列表实际长度抛出IndexOutOfBoundsException,这也是输入4个重复[0,0,0,0]时报错的直接原因。 - 语法不规范:开头的泛型声明
list<list<Integer>ms2不符合Java语法要求,正确的类型声明应该是List<List<Integer>>。 - 无意义的性能损耗:每次判断相等前都新建ArrayList拷贝子列表是多余操作,List接口的
equals方法本身就会按顺序对比两个列表的所有元素,内容完全一致就会返回true,不需要额外拷贝对象。
正确实现方式
方案1:利用LinkedHashSet实现(推荐)
Set天然具备去重特性,LinkedHashSet还可以保留元素的插入顺序,代码最简洁,时间复杂度优于双重循环的O(n²):
import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.Collections; public class NestedListDedupe { /** * 嵌套列表去重,保留重复元素第一次出现的位置 */ public static <T> List<List<T>> dedupe(List<List<T>> source) { return new ArrayList<>(new LinkedHashSet<>(source)); } /** * 嵌套列表去重,保留重复元素最后一次出现的位置(匹配给出的示例输出要求) */ public static <T> List<List<T>> dedupeKeepLast(List<List<T>> source) { Set<List<T>> set = new LinkedHashSet<>(); // 倒序遍历,让最后一次出现的元素优先存入Set for (int i = source.size() - 1; i >= 0; i--) { set.add(source.get(i)); } List<List<T>> result = new ArrayList<>(set); // 反转恢复原有顺序 Collections.reverse(result); return result; } public static void main(String[] args) { // 测试用例1 List<List<Integer>> test1 = new ArrayList<>(); test1.add(List.of(1,1,1)); test1.add(List.of(23,4,5)); test1.add(List.of(1,1,1)); System.out.println(dedupeKeepLast(test1)); // 输出 [[23, 4, 5], [1, 1, 1]],符合预期 // 测试用例2 List<List<Integer>> test2 = new ArrayList<>(); test2.add(List.of(0,0,0,0)); test2.add(List.of(0,0,0,0)); test2.add(List.of(0,0,0,0)); test2.add(List.of(0,0,0,0)); System.out.println(dedupeKeepLast(test2)); // 输出 [[0, 0, 0, 0]],符合预期 } }
方案2:修正后的双重循环实现
如果需要手动实现遍历逻辑,注意删除元素后不要立刻递增内层循环变量,避免漏判或索引越界:
public static <T> List<List<T>> dedupeByLoop(List<List<T>> source) { List<List<T>> result = new ArrayList<>(source); for (int i = 0; i < result.size(); i++) { for (int j = i + 1; j < result.size(); ) { if (result.get(i).equals(result.get(j))) { result.remove(j); // 删除元素后j不自增,下一个元素已经移到当前j的位置 } else { j++; } } } return result; }
注意:这个双重循环实现默认保留重复元素第一次出现的位置,如果要保留最后一次出现的位置,调整遍历顺序从后往前对比即可。
内容的提问来源于stack exchange,提问作者anantha Puneethchowdary
相关产品推荐
相关产品推荐

