How to Iterate Over a Stream With Indices

1. Overview

Java 8 Streams are not collections and elements cannot be accessed using their indices, but there are still a few tricks to make this possible.

In this short article, we’re going to look at how to iterate over a Stream using IntStream, StreamUtils, EntryStream, and Vavr‘s Stream.

2. Using Plain Java

We can navigate through a Stream using an Integer range, and also benefit from the fact that the original elements are in an array or a collection accessible by indices.

Let’s implement a method which iterates with indices and demonstrates this approach.

Simply put, we want to get an array of Strings and only select even indexed elements:

public List<String> getEvenIndexedStrings(String[] names) {
    List<String> evenIndexedNames = IntStream
      .range(0, names.length)
      .filter(i -> i % 2 == 0)
      .mapToObj(i -> names[i])
      .collect(Collectors.toList());
    
    return evenIndexedNames;
}

Let’s now test out the implementation:

@Test
public void whenCalled_thenReturnListOfEvenIndexedStrings() {
    String[] names 
      = {"Afrim", "Bashkim", "Besim", "Lulzim", "Durim", "Shpetim"};
    List<String> expectedResult 
      = Arrays.asList("Afrim", "Besim", "Durim");
    List<String> actualResult 
      = StreamIndices.getEvenIndexedStrings(names);
   
    assertEquals(expectedResult, actualResult);
}

3. Using StreamUtils

Another way to iterate with indices can be done using zipWithIndex() method of StreamUtils from the proton-pack library (the latest version can be found here).

First, you need to add it to your pom.xml:

<dependency>
    <groupId>com.codepoetics</groupId>
    <artifactId>protonpack</artifactId>
    <version>1.13</version>
</dependency>

Now, let’s look at the code:

public List<Indexed<String>> getEvenIndexedStrings(List<String> names) {
    List<Indexed<String>> list = StreamUtils
      .zipWithIndex(names.stream())
      .filter(i -> i.getIndex() % 2 == 0)
      .collect(Collectors.toList());
    
    return list;
}

The following tests this method and passes successfully:

@Test
public void whenCalled_thenReturnListOfEvenIndexedStrings() {
    List<String> names = Arrays.asList(
      "Afrim", "Bashkim", "Besim", "Lulzim", "Durim", "Shpetim");
    List<Indexed<String>> expectedResult = Arrays.asList(
      Indexed.index(0, "Afrim"), 
      Indexed.index(2, "Besim"), 
      Indexed.index(4, "Durim"));
    List<Indexed<String>> actualResult 
      = StreamIndices.getEvenIndexedStrings(names);
    
    assertEquals(expectedResult, actualResult);
}

4. Using StreamEx

We can also iterate with indexes using filterKeyValue() of EntryStream class from StreamEx library (the latest version can be found here). First, we need to add it to our pom.xml:

<dependency>
    <groupId>one.util</groupId>
    <artifactId>streamex</artifactId>
    <version>0.6.5</version>
</dependency>

Let’s see a simple application of this method using our previous example:

public List<String> getEvenIndexedStringsVersionTwo(List<String> names) {
    return EntryStream.of(names)
      .filterKeyValue((index, name) -> index % 2 == 0)
      .values()
      .toList();
}

We’ll use a similar test to test this:

@Test
public void whenCalled_thenReturnListOfEvenIndexedStringsVersionTwo() {
    String[] names 
      = {"Afrim", "Bashkim", "Besim", "Lulzim", "Durim", "Shpetim"};
    List<String> expectedResult 
      = Arrays.asList("Afrim", "Besim", "Durim");
    List<String> actualResult 
      = StreamIndices.getEvenIndexedStrings(names);
   
   assertEquals(expectedResult, actualResult);
}

5. Iteration Using Vavre‘s Stream

Another plausible way of iteration is using zipWithIndex() method of Vavr (previously known as Javaslang)’s Stream implementation:

public List<String> getOddIndexedStringsVersionTwo(String[] names) {
    return Stream
      .of(names)
      .zipWithIndex()
      .filter(tuple -> tuple._2 % 2 == 1)
      .map(tuple -> tuple._1)
      .toJavaList();
}

We can test this example with the following method:

@Test
public void whenCalled_thenReturnListOfOddStringsVersionTwo() {
    String[] names 
      = {"Afrim", "Bashkim", "Besim", "Lulzim", "Durim", "Shpetim"};
    List<String> expectedResult 
      = Arrays.asList("Bashkim", "Lulzim", "Shpetim");
    List<String> actualResult 
      = StreamIndices.getOddIndexedStringsVersionTwo(names);

    assertEquals(expectedResult, actualResult);
}

If you want to read more about Vavr, check this article.

6. Conclusion

In this quick tutorial, we saw four approaches on how to iterate through streams using indices. Streams have gotten a lot of attention and being able to also iterate through them with indices can be helpful.

There are a lot of features that are included in Java 8 Streams, some of which are already covered on VietMX’s Blog.

The code for all the examples explained here, and much more can be found over on GitHub.

Related posts:

A Guide to ConcurrentMap
Java Program to Find Minimum Element in an Array using Linear Search
Lớp Arrarys trong Java (Arrays Utility Class)
Java Program to Check if a Directed Graph is a Tree or Not Using DFS
Java Program to Implement Hash Tables with Quadratic Probing
Làm thế nào tạo instance của một class mà không gọi từ khóa new?
Introduction to Spring Cloud Netflix – Eureka
Java Program to Implement TreeSet API
Java Program to Implement String Matching Using Vectors
Java Program to Represent Graph Using Adjacency Matrix
Hướng dẫn sử dụng String Format trong Java
Java Program to do a Depth First Search/Traversal on a graph non-recursively
Lập trình đa luồng trong Java (Java Multi-threading)
Control Structures in Java
Removing all Nulls from a List in Java
A Guide to the ViewResolver in Spring MVC
Tránh lỗi ConcurrentModificationException trong Java như thế nào?
Write/Read cookies using HTTP and Read a file from the internet
Java Program to Implement LinkedHashMap API
Hướng dẫn Java Design Pattern – Abstract Factory
Weak References in Java
Guide to Spring @Autowired
Spring Boot Integration Testing with Embedded MongoDB
Running Spring Boot Applications With Minikube
Hướng dẫn Java Design Pattern – Adapter
Java Program to Represent Graph Using Linked List
Hướng dẫn sử dụng luồng vào ra ký tự trong Java
Từ khóa static và final trong java
Hướng dẫn Java Design Pattern – Transfer Object
Spring Cloud Bus
TreeSet và sử dụng Comparable, Comparator trong java
Java Program to Implement Adjacency Matrix