You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 07:30:52