Java去重List推荐用LinkedHashSet或Stream.distinct(),均保序且高效;自定义对象按字段去重需用Collectors.toMap();HashSet不保序,TreeSet可排序去重,手动遍历效率低不推荐。

Java中去除List重复元素,核心思路是借助具备唯一性约束的集合(如HashSet、LinkedHashSet、TreeSet)或Stream API来实现。选择哪种方式,取决于你是否需要保持原有顺序、是否要求元素可比较、以及对性能的要求。
用LinkedHashSet保持插入顺序去重
这是最常用也最推荐的方式,适合大多数场景——既去重,又保留原List中元素首次出现的顺序。
- 创建一个LinkedHashSet,把原List全部添加进去,自动去重且记序
- 再用这个Set构造新ArrayList(或清空原List后重新添加)
List<String> list = Arrays.asList("a", "b", "a", "c", "b");
List<String> uniqueList = new ArrayList<>(new LinkedHashSet<>(list));
注意:元素必须正确重写equals()和hashCode(),否则自定义对象去重会失效。
用Stream.distinct()一行解决(Java 8+)
函数式风格简洁清晰,同样默认保持原始顺序,底层也是基于LinkedHashSet实现的去重逻辑。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
立即学习“Java免费学习笔记(深入)”;
- 调用
stream().distinct().collect(Collectors.toList()) - 适用于临时去重、链式调用场景,可与其他Stream操作组合
List<Integer> nums = Arrays.asList(1, 2, 2, 3, 1); List<Integer> unique = nums.stream().distinct().collect(Collectors.toList());
按业务规则去重(如根据对象某个字段)
当List中是自定义对象(如User),而你只想根据id或name去重时,不能直接用HashSet——需配合Collectors.toMap()或自定义谓词。
- 用
toMap()以关键字段为key,保留第一个出现的对象 - 再取map.values()转为List,自然去重且保序(Java 9+可用
LinkedHashMap::new确保顺序)
List<User> users = ...;
List<User> uniqueById = users.stream()
.collect(Collectors.toMap(User::getId, u -> u, (u1, u2) -> u1, LinkedHashMap::new))
.values()
.stream()
.collect(Collectors.toList());
其他方式简要说明
HashSet适合不关心顺序的快速去重;TreeSet可用于需要排序后去重的场景(要求元素实现Comparable或传入Comparator);手动遍历+contains判断效率低,仅用于极小数据量或教学演示,不建议生产使用。
基本上就这些。选LinkedHashSet或Stream.distinct()覆盖90%需求,按字段去重稍复杂但很实用——关键还是看你的数据结构和业务约束。

















