Java中ArrayList去重需重写equals()和hashCode()方法,推荐用LinkedHashSet保持顺序,或Stream.distinct()函数式处理;临时按单字段去重可用Collectors.toMap()。

Java 中 ArrayList 本身不提供内置的“按自定义规则去重”功能,真正起作用的是对象自身的 equals() 和 hashCode() 方法。只要正确重写这两个方法,配合 Stream.distinct()、LinkedHashSet 或手动遍历,就能实现按业务字段去重。
重写 equals() 和 hashCode() 是前提
去重依赖对象是否“逻辑相等”,而 Java 默认的 equals() 比较的是引用地址。必须在自定义类中根据业务字段(比如 id、name、组合键)重写这两个方法:
-
必须同时重写:只改
equals()不改hashCode()会导致哈希集合(如HashSet)行为异常 -
字段保持一致:参与
equals()判断的字段,也必须参与hashCode()计算 - 推荐用 IDE 自动生成:IntelliJ 或 Eclipse 都支持选中字段一键生成,避免手写出错
用 LinkedHashSet 去重(推荐,保留顺序)
LinkedHashSet 既去重又保持插入顺序,适合大多数场景:
ArrayList<user> list = new ArrayList(); list.add(new User(1, "Alice")); list.add(new User(2, "Bob")); list.add(new User(1, "Alice")); // 重复 // 去重并保持原顺序 List<user> uniqueList = new ArrayList(new LinkedHashSet(list));</user></user>
原理:构造 LinkedHashSet 时会调用每个元素的 equals() 和 hashCode() 判断是否已存在。
用 Stream.distinct()(Java 8+,简洁函数式)
适合链式操作或配合其他流操作:
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
List<user> uniqueList = list.stream()
.distinct()
.collect(Collectors.toList());</user>
注意:distinct() 内部也是基于 equals()/hashCode(),所以仍需先重写这两个方法。
按单个字段去重(不改 equals,临时逻辑)
如果不想修改实体类,或需要多种去重策略(比如有时按 id、有时按 name),可用 Collectors.toMap() 实现字段级去重:
List<user> uniqueById = list.stream()
.collect(Collectors.toMap(
User::getId, // key:用 getId 作为去重依据
user -> user, // value:保留对象本身
(u1, u2) -> u1 // 冲突时保留第一个
))
.values()
.stream()
.collect(Collectors.toList());</user>
这种方式灵活,但不适用于复合条件(如 “id + name 相同才算重复”),此时建议还是重写 equals()。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










