最常用高效方式是用 LinkedHashSet 构造新 ArrayList,如 new ArrayList(new LinkedHashSet(list));也可用迭代器就地去重或 Stream.distinct(),均依赖正确实现的 equals() 和 hashCode()。

Java 中给 ArrayList 去重并保持原有顺序,最常用、高效且简洁的方式是借助 LinkedHashSet —— 它既去重,又按插入顺序保存元素。
用 LinkedHashSet 构造新列表(推荐)
这是最直接、可读性高、性能好的方法。前提是元素类型正确重写了 equals() 和 hashCode()(如 String、包装类、自定义类等)。
示例代码:
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "a", "c", "b"));
List<String> uniqueList = new ArrayList<>(new LinkedHashSet<>(list));
// 结果:["a", "b", "c"]
- 一行搞定,语义清晰
- 时间复杂度接近 O(n),空间略增(额外 HashSet)
- 原列表不受影响,适合函数式风格
就地去重(修改原列表)
如果必须复用原 ArrayList 对象(比如避免创建新对象),可用迭代器边遍历边删除重复项:
立即学习“Java免费学习笔记(深入)”;
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "a", "c", "b"));
Set<String> seen = new HashSet<>();
for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
String item = it.next();
if (!seen.add(item)) { // add() 返回 false 表示已存在
it.remove();
}
}
- 利用
HashSet.add()的返回值判断是否首次添加 - 必须用
Iterator.remove(),避免ConcurrentModificationException - 适用于内存敏感或明确要求复用原引用的场景
使用 Java 8 Stream(简洁但稍重)
借助 Stream 和 Collectors.toCollection() 可保持顺序:
List<String> list = Arrays.asList("a", "b", "a", "c", "b");
List<String> uniqueList = list.stream()
.distinct()
.collect(Collectors.toList());
-
distinct()内部基于LinkedHashSet,保证顺序和去重 - 代码声明式、易读,适合链式处理
- 有少量流开销,对超大列表略逊于纯集合方案,但通常可忽略
注意点
所有方法都依赖元素的 equals() 和 hashCode() 正确实现:
-
String、Integer等标准类默认支持 - 自定义对象务必重写这两个方法,否则去重失效(会按引用比较)
- 若需按特定字段去重(如只看 ID),应先映射或自定义
hashCode/equals,或改用Stream+filter配合临时 Set


















