1. 概述

有时,我们需要将多个列表中的数据合并在一起,将第一个列表的第一个元素与其在第二个列表中的对应项连接起来。

在这篇教程中,我们将学习几种方法来同时遍历两个ArrayList集合。我们将探讨循环、迭代器、流处理以及第三方工具来解决这个问题。

2. 问题陈述与用例

假设我们有两个列表,一个包含国家名称,另一个包含国家的电话代码。并且假设在第二个列表中,任何给定索引处的电话代码都对应于第一个列表中相同索引处的国家名称。

我们希望将第二个列表中的正确电话代码与第一个列表中对应的国家名称关联起来。

在Java中,这个用例并没有现成的解决方案。然而,我们可以通过几种方式实现它。

首先,让我们创建两个List对象,用于处理:

List<String> countryName = List.of("USA", "UK", "Germany", "India");
List<String> countryCode = List.of("+1", "+44", "+49", "+91");

这里,我们有两个大小相同的列表,因为每个国家都应该有一个代码。如果列表的大小不同,我们的解决方案可能无法正常工作。

我们想要处理这两个列表,并为每个国家获取正确的代码。我们将测试每个解决方案的预期输出:

assertThat(processedList)
  .containsExactly("USA: +1", "UK: +44", "Germany: +49", "India: +91");

3. 使用for循环进行迭代

让我们从使用for循环简单地遍历两个列表开始:

for (int i = 0; i < countryName.size(); i++) {
    String processedData = String.format("%s: %s", countryName.get(i), countryCode.get(i));
    processedList.add(processedData);
}

在这里,我们在两个列表上使用了相同的索引i调用get()方法来配对我们的项目。循环结束后,processedList将包含正确的结果。

4. 使用Collection迭代器

我们也可以使用Collection接口的iterator()方法获取一个Iterator实例。我们将首先为两个列表获取Iterator实例:

Iterator<String> nameIterator = countryName.iterator();
Iterator<String> codeIterator = countryCode.iterator();

我们将使用一个while循环一起管理这两个迭代器:

while (nameIterator.hasNext() && codeIterator.hasNext()) {
    String processedData = String.format("%s: %s", nameIterator.next(), codeIterator.next());
    processedList.add(processedData);
}

while循环通过调用hasNext()确保两个迭代器仍有值,在循环内部,我们使用next()获取下一对值。

5. 使用StreamUtilszip()方法处理

可以说,我们的目标是将每个列表的数据附加到另一个列表上,或者一起处理这对数据。这被称为合并两个集合的对。许多库提供了现成的实现,我们可以直接使用。

让我们使用Spring的StreamUtils库的zip()方法,并提供一个Lambda表达式来创建我们的组合值。

5.1. 依赖性

首先,我们应该在pom.xml文件中添加Spring Data的依赖项:

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-commons</artifactId>
    <version>2.7.5</version>
</dependency>

5.2. 实现

我们将传递两个列表的流和一个Lambda函数给zip()方法。Lambda将包含处理逻辑,我们将使用collect()方法收集所有处理后的数据到一个列表中。

List<String> processedList = StreamUtils.zip(
  countryName.stream(), 
  countryCode.stream(),
  (name, code) -> String.format("%s: %s", name, code))
  .collect(Collectors.toList());

zip()的输出是一个流,我们将其收集起来。作为第三个参数提供的BiFunction,在输入列表的两个流之后,用于创建我们可以在最后收集到单个列表中的正确配对元素的流。

我们需要注意的是,这种方法利用了Java流的所有优点,包括过滤和映射输入数据、过滤输出数据,以及尽可能减少内存使用。

6. 总结

在这篇教程中,我们了解了遍历两个ArrayList集合的不同方法。

如往常一样,示例的完整源代码可在GitHub上找到。