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

不使用distinct()方法基于Java 8 Stream API实现整数列表去重

问题:仅使用Java 8 Stream API、不调用distinct()实现整数列表去重

题面要求:从整数列表中提取所有不重复元素,实现过程仅可使用Java 8 Stream API,禁止直接调用distinct()方法。常规Stream去重直接调用distinct()是最简便的方案,但该路径被题目明确排除。

下面是几种可运行的实现方案,都是实际开发中常用的写法:


方案1:filter()配合Set记录已遍历元素(面试最高频写法)

核心是利用Set.add()方法的返回值特性:元素首次插入Set时返回true,元素已存在时返回false,刚好可以作为filter的放行判断条件。

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class StreamDistinctDemo {
    public static List<Integer> getUniqueElements(List<Integer> originList) {
        Set<Integer> visited = new HashSet<>();
        return originList.stream()
                .filter(num -> visited.add(num))
                .collect(Collectors.toList());
    }
}

注意:这个写法在顺序流下完全没问题,如果要适配并行流,把new HashSet<>()替换成ConcurrentHashMap.newKeySet()避免线程安全问题即可。


方案2:利用Collectors.toMap()的键去重特性

Map本身不允许重复键,可以把元素本身作为Map的key,收集完成后取所有key就是去重后的结果:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class StreamDistinctDemo {
    public static List<Integer> getUniqueElements(List<Integer> originList) {
        return new ArrayList<>(
                originList.stream()
                        .collect(Collectors.toMap(
                                num -> num,
                                num -> Boolean.TRUE,
                                (oldVal, newVal) -> oldVal
                        )).keySet()
        );
    }
}

这里第三个参数是重复key的合并策略,遇到重复元素直接保留已存在的key即可,不会抛出重复键的异常。


方案3:自定义收集器实现

如果想完全走Stream收集器链路,也可以直接把元素收集到Set中实现去重,再转成List返回:

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.stream.Collectors;

public class StreamDistinctDemo {
    public static List<Integer> getUniqueElements(List<Integer> originList) {
        // 要保序就把HashSet换成LinkedHashSet
        return originList.stream()
                .collect(LinkedHashSet::new, LinkedHashSet::add, LinkedHashSet::addAll)
                .stream()
                .collect(Collectors.toList());
    }
}

这个写法本质和方案1逻辑一致,只是把状态判断封装到了收集器的累加逻辑里,并行流场景下会自动调用集合的addAll方法合并多个分片的结果,比方案1的filter写法更适配并行场景。


以上三种写法都没有调用Stream的distinct()方法,保序场景下返回结果的元素顺序和原列表首次出现的顺序一致,和直接调用distinct()的去重效果完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 17:30:50