Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

Sometimes, we have data in multiple lists that we need to join together, connecting the first item from the first list with its counterpart in the second, and so on.

In this tutorial, we’ll learn a few ways to iterate through two ArrayList collections simultaneously. We’ll look at loops, iterators, streaming, and third-party utilities to solve the problem.

2. Problem Statement and Use Case

Let’s take an example where we have two lists, one containing country names and the second one containing the countries’ phone codes. And suppose that in the second list, the phone code at any given index corresponds to the country name at the same index in the first list.

We want to associate the correct country code from the second list with its corresponding country name from the first list.

There’s no existing out-of-the-box solution for this use case in Java. However, there are a few ways we can achieve this.

Let’s first create two List objects that we’ll be using for processing:

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

Here, we have two lists of the same size, since each country should have a code. Our solutions might not work if the lists are of different sizes.

We want to process both lists and get the correct code for each country. We’ll test our expected output for each solution:

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

3. Iterate Using a for Loop

Let’s start with the simplest way to iterate two lists using a for loop:

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

Here, we’ve used get() on each of the two lists with the same index – i – to pair up our items. At the end of the loop, processedList will contain the correct result.

4. Iterate Using Collection Iterator

We can also use the iterator() method of the Collection interface to get an Iterator instance. We’ll first get the Iterator instances for both lists:

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

We’ll use a while loop to manage both iterators together:

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

The while loop calls hasNext() to ensure that both iterators still have values, and within the loop, we’re picking the next pair of values using next().

5. Process Using StreamUtils zip() Method

We can say that our goal is to attach the data from each list to each other, or process the pair together. This is also known as zipping a pair of collections. Various libraries provide an implementation of this process that we can use out of the box.

Let’s use the zip() method of Spring’s StreamUtils library and provide a Lambda to create our combined values.

5.1. Dependency

First, we should add the Spring Data dependency in the pom.xml file:

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

5.2. Implementation

We’ll pass the stream of our lists and a lambda function to the zip() method. The lambda will have the processing logic, and we’ll use the collect() method to get all the processed data in a list.

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

The output of zip() is a Stream that we collect. The BiFunction we provide as the third parameter, after the two Streams of our input lists, is used to create the elements of the Stream that we can then collect at the end to a single list that contains the right pairings.

We should note that this method has all the benefits of Java Streams, including filtering and mapping the input data, filtering the output data, and keeping as little as possible in memory.

6. Conclusion

In this tutorial, we’ve learned different ways to iterate through two ArrayLists simultaneously.

As always, the complete source code of the examples is available over on GitHub.

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
1 Comment
Oldest
Newest
Inline Feedbacks
View all comments
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.