ArrayList去重首选LinkedHashSet保持顺序,或Stream.distinct()链式处理;自定义字段去重用toMap或filter+Set;过滤用filter()或removeIf()。

Java 中 ArrayList 去重和过滤数据,核心在于借助集合特性(如 Set 的唯一性)或 Stream API 的函数式操作,避免手动遍历+嵌套判断的低效写法。关键不是“能不能”,而是“选对方法、注意细节”。
用 LinkedHashSet 一步去重(保持插入顺序)
这是最常用、简洁且保留原顺序的方式。因为 LinkedHashSet 既去重,又按插入顺序存储元素。
适用场景:元素类型已正确重写 equals() 和 hashCode()(如 String、Integer、自定义类)。
- 直接构造新列表:new ArrayList(new LinkedHashSet(originalList))
- 若需复用原引用,可清空后批量添加:
list.clear(); list.addAll(new LinkedHashSet(list)); - 注意:原始
ArrayList必须是可变的(非Collections.unmodifiableList等不可变视图)
用 Stream.distinct() 过滤重复元素(推荐 Java 8+)
distinct() 是 Stream 的中间操作,底层依赖元素的 equals()/hashCode(),天然支持链式调用,适合复合过滤场景。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 基础去重:
List<string> unique = list.stream().distinct().collect(Collectors.toList());</string> - 结合其他条件(如非空且长度 > 2):
list.stream().filter(Objects::nonNull).filter(s -> s.length() > 2).distinct().collect(Collectors.toList()); - 对对象列表去重时,确保对象类重写了
equals和hashCode;否则默认比较引用,无法去重
按自定义规则去重(比如根据对象某个字段)
当不能或不想改对象的 equals 方法时,可用 Collectors.toMap() 或辅助 Set 记录已见键。
- 用
toMap保留第一个出现的对象(以 id 为 key):
List<Person> uniqueById = list.stream()<br> .collect(Collectors.collectingAndThen(<br> Collectors.toMap(Person::getId, p -> p, (a, b) -> a),<br> map -> new ArrayList<>(map.values())<br> )); - 用
filter+ 自定义 Set 记录已处理的字段值:
Set<Integer> seenIds = ConcurrentHashMap.newKeySet();<br> List<Person> filtered = list.stream()<br> .filter(p -> seenIds.add(p.getId()))<br> .collect(Collectors.toList());
(注意:多线程环境用ConcurrentHashMap.newKeySet(),单线程可用HashSet)
过滤数据(非去重):用 stream.filter() 最直观
过滤是常见需求,比如排除 null、空字符串、负数、过期对象等,filter() 配合 Lambda 表达式非常清晰。
- 基本用法:
list.stream().filter(x -> x != null && x > 0).collect(Collectors.toList()); - 字符串常用过滤:
filter(s -> s != null && !s.trim().isEmpty()) - 对象属性过滤:
filter(p -> "active".equals(p.getStatus()) && p.getAge() >= 18) - 注意:
filter不改变原列表,返回新列表;如需修改原列表,可用removeIf()(会就地删除):list.removeIf(p -> p.getScore()

















