杰瑞科技汇

Java List如何高效合并两个List?

Java List “加” List终极指南:从addAll()到Stream流,一篇搞定所有合并场景!

Meta描述:

还在为Java中如何合并两个List而烦恼?本文详细讲解addAll()Collections.addAll()、Java 8 Stream流、循环遍历等多种List合并方法,附代码实例与性能对比,助你轻松掌握Java List加List技巧,解决开发难题!

Java List如何高效合并两个List?-图1
(图片来源网络,侵删)

引言:为什么我们需要合并List?

在Java开发中,List是我们最常用的集合类之一,无论是处理业务数据、API响应,还是简单的数据聚合,我们经常会遇到需要将两个或多个List合并成一个List的场景。

  • 合并两个查询结果集。
  • 聚合不同来源的用户列表。
  • 将分页查询的数据合并成一份完整列表。

“Java list 加list”这个搜索词背后,是开发者对“合并”这一具体操作最直接、最朴素的需求,他们想知道“在Java里,如何把两个List拼在一起?”,本文将围绕这个核心问题,提供最全面、最实用的答案。


基础入门:最简单直接的合并方法——addAll()

对于初学者来说,List接口自带的addAll()方法是合并List最直观、最容易理解的方式。

使用目标List的addAll()方法

这是最常见的一种方式,将一个List中的所有元素追加到另一个List的末尾。

Java List如何高效合并两个List?-图2
(图片来源网络,侵删)

核心语法: list1.addAll(list2);

代码示例:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ListAddExample1 {
    public static void main(String[] args) {
        // 创建两个List
        List<String> list1 = new ArrayList<>(Arrays.asList("Java", "Python", "C++"));
        List<String> list2 = new ArrayList<>(Arrays.asList("Go", "Rust", "JavaScript"));
        System.out.println("合并前 list1: " + list1);
        System.out.println("合并前 list2: " + list2);
        // 将list2的所有元素添加到list1中
        list1.addAll(list2);
        System.out.println("合并后 list1: " + list1);
        System.out.println("合并后 list2: " + list2); // list2保持不变
    }
}

执行结果:

合并前 list1: [Java, Python, C++]
合并前 list2: [Go, Rust, JavaScript]
合并后 list1: [Java, Python, C++, Go, Rust, JavaScript]
合并后 list2: [Go, Rust, JavaScript]

⚠️ 重要注意事项:

Java List如何高效合并两个List?-图3
(图片来源网络,侵删)
  1. 修改源List:此方法会直接修改list1list1本身成为了合并后的新列表,如果不想修改原始list1,你需要先创建一个它的副本。
  2. 元素引用addAll()操作是浅拷贝,如果List中存放的是对象(非基本类型),合并后的List中的元素与原始List中的元素指向的是同一个对象引用,修改其中一个List中的对象,会影响另一个。

修正版(不修改原始List):

// 创建一个新的List,包含list1的所有元素,然后再添加list2
List<String> mergedList = new ArrayList<>(list1); // 创建list1的副本
mergedList.addAll(list2);
System.out.println("原始 list1: " + list1);
System.out.println("合并后新List: " + mergedList);

使用Collections.addAll()

java.util.Collections工具类也提供了一个addAll()方法,但它接收一个目标Collection和一个可变数量的元素。

核心语法: Collections.addAll(destinationList, sourceList.toArray());

代码示例:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class ListAddExample2 {
    public static void main(String[] args) {
        List<String> list1 = new ArrayList<>(Arrays.asList("A", "B"));
        List<String> list2 = new ArrayList<>(Arrays.asList("C", "D"));
        // 创建一个新List来存储合并结果
        List<String> mergedList = new ArrayList<>(list1);
        // 将list2的所有元素添加到mergedList中
        Collections.addAll(mergedList, list2.toArray(new String[0]));
        System.out.println("合并后: " + mergedList);
    }
}

这种方法与方法一类似,也需要手动处理原始List的拷贝问题。


进阶玩法:Java 8 Stream流式合并

如果你正在使用Java 8或更高版本,那么Stream API无疑是处理集合合并的“神器”,它代码更简洁,功能更强大,并且可以轻松实现去重、过滤等复杂操作。

使用Stream.concat()

Stream.concat()是专门用于合并两个流的静态方法,非常优雅。

核心语法: List<T> mergedList = Stream.concat(list1.stream(), list2.stream()).collect(Collectors.toList());

代码示例:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ListAddExample3 {
    public static void main(String[] args) {
        List<Integer> list1 = Arrays.asList(1, 2, 3);
        List<Integer> list2 = Arrays.asList(3, 4, 5);
        // 使用Stream.concat合并
        List<Integer> mergedList = Stream.concat(list1.stream(), list2.stream())
                                         .collect(Collectors.toList());
        System.out.println("合并后: " + mergedList); // 输出: [1, 2, 3, 3, 4, 5]
    }
}

Stream流合并的优势:

  1. 不可变性:此方法不会修改原始的list1list2,始终返回一个新的List,符合函数式编程思想,更安全。
  2. 链式操作:可以在合并后无缝衔接其他Stream操作,如distinct()(去重)、filter()(过滤)、sorted()(排序)等。

进阶示例:合并并去重

List<Integer> mergedAndDistinctList = Stream.concat(list1.stream(), list2.stream())
                                           .distinct() // 去重
                                           .collect(Collectors.toList());
System.out.println("合并并去重后: " + mergedAndDistinctList); // 输出: [1, 2, 3, 4, 5]

性能与场景对比:我该用哪种方法?

没有最好的方法,只有最合适的方法,下面我们从几个维度进行对比:

方法 代码简洁性 是否修改原List 功能扩展性 性能 推荐场景
list1.addAll(list2) 中等 是(修改list1) 简单、直接的追加,且明确需要修改原List时。
Collections.addAll() 中等 否(需手动拷贝) addAll类似,但需要将源List转为数组。
Stream.concat() 极强 中等 推荐! Java 8+环境下的首选,尤其需要链式操作(去重、排序等)时。
循环遍历 for-each 否(需手动拷贝) 低(但差异不大) 不推荐,除非在循环中需要对每个元素进行特殊处理时。

性能小贴士: 对于超大规模的List(例如百万级数据),addAll()方法在底层优化上通常会比Stream.concat()有微弱的优势,因为它避免了流操作带来的额外开销,但在绝大多数业务场景下,这种性能差异可以忽略不计,代码的可读性和可维护性往往比那一点点性能提升更重要。


高级技巧:合并多个List

如果需要合并的不是一个,而是一组List,该怎么办?

使用Stream.of()flatMap

当有多个List变量时,可以使用Stream.of()将它们包装成一个流,然后通过flatMap将每个List流“压平”成一个元素流。

代码示例:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class MergeMultipleLists {
    public static void main(String[] args) {
        List<String> list1 = Arrays.asList("A", "B");
        List<String> list2 = Arrays.asList("C", "D");
        List<String> list3 = Arrays.asList("E", "F");
        // 使用Stream.of和flatMap合并多个List
        List<String> allMerged = Stream.of(list1, list2, list3)
                                      .flatMap(List::stream) // 将每个List转换为流,然后合并成一个流
                                      .collect(Collectors.toList());
        System.out.println("合并多个List后: " + allMerged); // 输出: [A, B, C, D, E, F]
    }
}

使用List.addAll()循环

对于Java 8之前的版本,或者不习惯使用Stream的开发者,可以通过循环来实现。

代码示例:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MergeMultipleListsLegacy {
    public static void main(String[] args) {
        List<Integer> list1 = Arrays.asList(1, 2);
        List<Integer> list2 = Arrays.asList(3, 4);
        List<Integer> list3 = Arrays.asList(5, 6);
        List<Integer> allMerged = new ArrayList<>();
        allMerged.addAll(list1);
        allMerged.addAll(list2);
        allMerged.addAll(list3);
        System.out.println("合并多个List后: " + allMerged);
    }
}

Java List合并的最佳实践

  1. 如果你使用的是Java 8+强烈推荐使用Stream.concat(),它不仅代码优雅,更重要的是它不改变原始数据,并且提供了无与伦比的扩展性,在需要去重、排序时,它能让你写出非常干净的业务逻辑。
  2. 如果你只需要简单追加,且不介意修改原Listlist1.addAll(list2) 是一个高效且直接的选择,但请务必注意它会修改list1
  3. 合并多个ListStream.of(...).flatMap(List::stream) 是处理不定数量List合并的利器。
  4. 始终考虑不可变性:在大多数现代应用开发中,避免修改原始对象是一种良好的编程习惯,可以减少很多潜在的bug,即使使用addAll(),也建议先拷贝再操作,或者直接使用Stream方案。

希望这篇“Java list 加list”终极指南能真正解决你的开发难题,从基础到高级,从原理到实践,我们已为你铺平了所有道路,选择最适合你当前场景的方法,写出更优雅、更健壮的Java代码吧!


分享:
扫描分享到社交APP
上一篇
下一篇