最直接合并两个List的方式是调用目标可变列表的addAll()方法,它将源列表元素追加到目标末尾且不修改源列表;注意目标列表须为ArrayList等可变类型,否则抛UnsupportedOperationException。

用 addAll() 合并两个 List 最直接
Java 中合并两个 List,最常用、最安全的方式就是调用目标列表的 addAll() 方法。它会把源列表所有元素追加到目标列表末尾,不改变源列表本身。
注意:目标列表必须是可变的(比如 ArrayList),不能是 Collections.unmodifiableList() 或 Arrays.asList() 返回的固定大小列表,否则运行时抛出 UnsupportedOperationException。
- 如果目标列表是新创建的空列表,适合做“无副作用合并”
- 如果目标列表已有数据,
addAll()是就地修改,原对象内容会变 - 源列表和目标列表类型需兼容(如都是
List),否则编译报错
Listlist1 = new ArrayList<>(Arrays.asList("a", "b")); List list2 = Arrays.asList("c", "d"); // 不可变,但可作为源 list1.addAll(list2); // ✅ 正确:list1 变成 ["a", "b", "c", "d"]
合并时去重?用 Stream + distinct() 更可控
原生 addAll() 不去重。若需要合并后唯一元素,推荐用 Stream 流式处理,尤其在 Java 8+ 环境下。
关键点:必须确保元素实现了 equals() 和 hashCode()(对自定义对象尤其重要),否则 distinct() 无法正确识别重复项。
立即学习“Java免费学习笔记(深入)”;
-
Stream.concat()可连接两个流,再链式调用distinct()和collect() - 结果默认是
ArrayList,但顺序保持原始插入顺序(LinkedHashSet语义) - 性能上比手动遍历
contains()高,尤其数据量大时
Lista = Arrays.asList(1, 2, 3); List b = Arrays.asList(2, 3, 4); List merged = Stream.concat(a.stream(), b.stream()) .distinct() .collect(Collectors.toList()); // [1, 2, 3, 4]
CollectionUtils.union() 看似方便,但要注意 Apache Commons 版本差异
Apache Commons Collections 的 CollectionUtils.union() 能直接返回去重后的合并结果,但它返回的是 Collection 接口类型,不是 List,且行为因版本而异:
- 3.x 版本中,
union()返回的是Set(无序),即使输入是List - 4.4+ 版本新增了
CollectionUtils.unionAsList(),才保证返回List并保留顺序 - 依赖第三方库意味着增加包体积和潜在冲突,简单场景不建议只为合并引入 Commons
如果你已在项目中使用 Commons 且版本 ≥ 4.4,可以这样写:
Listresult = CollectionUtils.unionAsList(list1, list2);
避免踩坑:不要用 Arrays.asList() 直接合并
常见错误是想“一行合并”,于是写:Arrays.asList(list1, list2) —— 这实际创建了一个包含两个 List 引用的 List,根本不是元素级合并。>
另一个陷阱是误用 Arrays.asList() 包装数组后调用 addAll():它返回的是固定大小列表,addAll() 会失败。
-
Arrays.asList("x", "y")返回不可扩容列表,add()或addAll()抛异常 - 要安全操作,先套一层
new ArrayList() - 泛型通配符(如
List extends Number>)会导致addAll()编译失败,需显式转型或改用原始类型
合并逻辑越简单,越该用原生 API;复杂需求(如按字段合并、差集、交集)再考虑 Guava 或 Commons。










