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

如何不使用Set接口移除列表重复元素?求移除指定元素1的更优方案

移除列表特定元素与无Set去重方案

一、移除列表中的数字1:修正你的现有方案

你当前使用的list.removeIf(el->Collections.frequency(list, el)>1);存在两个问题:

  1. 逻辑偏差:这个条件会移除所有出现次数大于1的元素,而非仅移除数字1。比如列表若为[1,2,1,3,3],执行后会同时删掉1和3,剩下[2],不符合需求。
  2. 效率低下:Collections.frequency()每次都会遍历整个列表,时间复杂度为O(n²),数据量大时性能很差。

最优写法

直接判断元素是否为1即可,时间复杂度O(n),简洁高效:

list.removeIf(el -> el.equals(1));

(如果确定元素在Integer缓存范围内[-128,127],用el == 1也可以,但equals更稳妥)


二、不使用Set接口移除重复元素的方案

根据是否需要保留元素原始顺序,有以下几种可行方案:

1. 保留原始顺序:临时列表记录+反向遍历

反向遍历可避免移除元素导致的索引偏移问题,逻辑清晰:

ArrayList<Integer> seen = new ArrayList<>();
// 从后往前遍历,避免移除元素后索引错乱
for (int i = list.size() - 1; i >= 0; i--) {
    Integer num = list.get(i);
    if (seen.contains(num)) {
        list.remove(i);
    } else {
        seen.add(num);
    }
}

时间复杂度O(n²),适合中小规模列表。

2. 保留原始顺序:Stream自定义过滤

用Stream结合内部状态容器实现过滤,代码更简洁:

ArrayList<Integer> uniqueList = list.stream()
        .filter(new Predicate<Integer>() {
            private final ArrayList<Integer> seen = new ArrayList<>();
            @Override
            public boolean test(Integer num) {
                boolean notSeen = !seen.contains(num);
                if (notSeen) seen.add(num);
                return notSeen;
            }
        })
        .collect(Collectors.toCollection(ArrayList::new));

本质和方案1逻辑一致,时间复杂度同样为O(n²)。

3. 不要求原始顺序:排序后移除相邻重复项

如果可以接受元素顺序改变,排序后移除相邻重复项的性能最优,时间复杂度由排序决定为O(n log n):

Collections.sort(list);
int i = 1;
while (i < list.size()) {
    if (list.get(i).equals(list.get(i-1))) {
        list.remove(i);
    } else {
        i++;
    }
}

内容的提问来源于stack exchange,提问作者Dhaivat Joshi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 07:16:04