java面试中list去重关键在三场景:提取单属性需filter(null)防npe;多属性扁平化用flatmap而非map;找重复对象用groupingby+filter+flatmap,空值须前置校验。

面试常考的不是“会不会用 map”,而是能不能根据具体场景选对操作、避开典型陷阱。关键在三点:提取单属性、提取多属性、识别重复项——每种都对应不同 Stream 组合逻辑,写错一行就可能丢分。
提取单个属性并去重
最基础也最容易出错。比如从 List<user></user> 中取所有不重复的邮箱:
- 正确写法:
users.stream().map(User::getEmail).filter(Objects::nonNull).distinct().collect(Collectors.toList()) - 常见错误:漏掉
filter(Objects::nonNull),一旦有 null 邮箱,distinct()会抛NullPointerException - 进阶选择:若结果只需唯一性、不关心顺序,用
Collectors.toSet()比toList()更语义清晰;若需不可变集合,Java 10+ 可用Collectors.toUnmodifiableList()
一次性提取多个属性(扁平化)
当一个对象含多个同类型字段(如 Bank 的 ossIdCn 和 ossIdEn),要合并去重,必须用 flatMap:
-
flatMap把每个对象转成一个流(比如两个 ID → 两个元素的流),再把所有子流压平成一个大流 - 示例:
banks.stream().flatMap(b -> Stream.of(b.getOssIdCn(), b.getOssIdEn())).filter(Objects::nonNull).distinct().collect(Collectors.toList()) - 不能用
map:它返回的是Stream<object></object>或Stream<list></list>,后续distinct()对的是数组/列表对象本身,不是里面的值
找出基于某属性的全部重复对象
这题高频且易被误解。不是“去重”,而是“把所有重复的实例都捞出来”——比如 osName 相同的所有 Computer 对象:
- 核心是分组 + 过滤 + 展开:
computers.stream().collect(Collectors.groupingBy(Computer::getOsName)).entrySet().stream().filter(e -> e.getValue().size() > 1).flatMap(e -> e.getValue().stream()).collect(Collectors.toList()) - 注意顺序:默认
groupingBy保持插入顺序,所以结果中重复项的相对顺序和原列表一致 - 空值防护:如果
getOsName()可能为 null,得提前filter(c -> c.getOsName() != null),否则分组时 null 键会导致异常或逻辑错乱
保持原始顺序的轻量替代方案
当数据量大、只关心“哪些值重复了”,不需要所有重复对象时,可避免分组开销:
- 先统计频次:
Map<string long> countMap = computers.stream().collect(Collectors.groupingBy(Computer::getOsName, Collectors.counting()))</string> - 再筛选键:
countMap.entrySet().stream().filter(e -> e.getValue() > 1).map(Map.Entry::getKey).collect(Collectors.toList()) - 内存友好:比全量分组少存对象引用,适合百万级数据预检
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











