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:

Java Program to Find the Nearest Neighbor Using K-D Tree Search
@DynamicUpdate with Spring Data JPA
Spring Webflux and CORS
Encode/Decode to/from Base64
@Order in Spring
Java Program to Find MST (Minimum Spanning Tree) using Kruskal’s Algorithm
Java Program to Implement Hash Tables Chaining with Binary Trees
SOAP Web service: Upload và Download file sử dụng MTOM trong JAX-WS
A Guide to Apache Commons Collections CollectionUtils
Java Program to Implement the Alexander Bogomolny’s UnOrdered Permutation Algorithm for Elements Fro...
Spring Boot with Multiple SQL Import Files
Java Scanner hasNext() vs. hasNextLine()
Spring Boot: Customize the Jackson ObjectMapper
Java Program to Perform Inorder Non-Recursive Traversal of a Given Binary Tree
Jackson Annotation Examples
Validations for Enum Types
Collection trong java
A Guide to the Java LinkedList
Lớp Properties trong java
Guide to the Synchronized Keyword in Java
Truyền giá trị và tham chiếu trong java
Java Program to Perform Encoding of a Message Using Matrix Multiplication
Java – Reader to InputStream
Đồng bộ hóa các luồng trong Java
Toán tử trong java
Spring Boot - Cloud Configuration Server
Java Program to Find ith Largest Number from a Given List Using Order-Statistic Algorithm
Java Program to Perform String Matching Using String Library
Prevent Brute Force Authentication Attempts with Spring Security
Check If a String Is Numeric in Java
The Java 8 Stream API Tutorial
Java Program to Check Whether a Directed Graph Contains a Eulerian Path