How to Use Index With forEach in Java

MD Aminul Islam Feb 12, 2024
  1. Use the forEach() Method With an Array Index Using the IntStream.range
  2. Use the forEach() Method With a List and HashMap Index
  3. Use the forEach() With Index Using the AtomicInteger Method
  4. Conclusion
How to Use Index With forEach in Java

You can follow this Java article if you want to use the Java forEach() method with a specific index. Sometimes, we must perform a particular task related to a specific index.

In this article, we will learn how to use the forEach() function with the combination of indexes. Also, we will cover the topic by using necessary examples and explanations to make the topic easier.

In general, the forEach() method doesn’t allow us to use an index with it, but there are some ways to do this. For this purpose, we must use the IntStream.range() method.

Use the forEach() Method With an Array Index Using the IntStream.range

The enhanced foreach loop introduced in Java 5 made this task more straightforward and readable. However, one limitation of the foreach loop is its inability to directly access the index of the current element.

This is where the IntStream.range method combined with Java 8’s Stream API comes into play, offering a neat solution to iterate over a collection or an array with access to the index.

The primary purpose of using IntStream.range in conjunction with foreach is to iterate over elements while keeping track of their indices. This approach is particularly useful in scenarios where you need to use the index for calculations, conditional logic, or accessing another collection in parallel.

import java.util.stream.IntStream;

public class ForeachWithIndex {
  public static void main(String[] args) {
    String[] fruits = {"Apple", "Banana", "Cherry", "Date"};

    IntStream.range(0, fruits.length)
        .forEach(i -> System.out.println("Index: " + i + ", Fruit: " + fruits[i]));
  }
}

In this code, we’re using IntStream.range(0, fruits.length) to generate a stream of integers representing the indices of the fruits array. The forEach method is then used to iterate over this stream.

Inside the lambda expression passed to forEach, i represents the current index, and we use it to access and print the corresponding element in the fruits array. This approach maintains the readability and simplicity of a foreach loop while providing access to the index.

Output:

java foreach with index - output 1

Use the forEach() Method With a List and HashMap Index

Combining Java Streams with a HashMap offers a neat way to iterate over a list with index information. This technique is especially useful when you need to maintain a reference to the index of each element in a list, which is not directly possible with the traditional forEach method.

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

public class JavaForEachIndex {
  public static void main(String[] args) {
    // Creating a list of strings
    List<String> StrList = Arrays.asList("A", "B", "C", "D", "E");

    // Creating and populating a HashMap using Stream
    HashMap<Integer, String> Collection = StrList.stream().collect(HashMap<Integer, String>::new,
        (MyMap, StreamVal) -> MyMap.put(MyMap.size(), StreamVal), (MyMap, map2) -> {});

    // Iterating over the HashMap using forEach
    Collection.forEach(
        (index, val) -> System.out.println("Value of list element at " + index + " = " + val));
  }
}

In this code snippet, we start by creating a list of strings. We then use Java Streams to process this list.

The collect method, along with a series of lambda expressions, is employed to populate a HashMap. The first lambda expression in the collect method (MyMap, StreamVal) -> MyMap.put(MyMap.size(), StreamVal) is responsible for putting elements into the map, with the map’s current size serving as the key (index) and the stream value as the value.

Finally, we use forEach on the HashMap to iterate through the list, now having access to both the index and the value.

Output:

java foreach with index - output 2

Use the forEach() With Index Using the AtomicInteger Method

In Java, the enhanced foreach loop provides a simple and clear way to iterate over collections. However, it cannot directly access the index of the current element. In order to overcome this limitation, one practical approach is using AtomicInteger.

AtomicInteger is a class in the java.util.concurrent.atomic package that provides an integer value that can be updated atomically. In the context of a foreach loop, it can act as a safe and efficient counter.

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class ForeachWithAtomicIndex {
  public static void main(String[] args) {
    List<String> items = Arrays.asList("Apple", "Banana", "Cherry", "Date");
    AtomicInteger index = new AtomicInteger();

    items.forEach(
        item -> { System.out.println("Index: " + index.getAndIncrement() + ", Item: " + item); });
  }
}

In our code, we create a list of strings items. We then initialize an AtomicInteger named index.

In the foreach loop, we use a lambda expression where item represents the current element of the list. Within the lambda, index.getAndIncrement() is called to get the current index and then increment it for the next iteration.

This approach allows us to safely and effectively iterate over the list while maintaining an accurate index.

Output:

java foreach with index - output 3

Conclusion

In summary, this article presents three innovative methods to utilize Java’s forEach loop with indices, a feature not directly available in the standard forEach implementation. We began with the IntStream.range technique, ideal for arrays, where indices are generated through a stream of integers.

This method maintains the simplicity of forEach while adding the capability to access indices.

Subsequently, we explored using a combination of Java Streams and HashMap for lists. This approach maps each element to its index, offering a convenient way to track and access elements by their positions.

It’s particularly useful when dealing with lists where the order of elements is significant.

Finally, we examined the use of AtomicInteger with forEach for thread-safe index tracking. This method is effective in concurrent scenarios, ensuring accurate indexing even in multi-threaded environments.

MD Aminul Islam avatar MD Aminul Islam avatar

Aminul Is an Expert Technical Writer and Full-Stack Developer. He has hands-on working experience on numerous Developer Platforms and SAAS startups. He is highly skilled in numerous Programming languages and Frameworks. He can write professional technical articles like Reviews, Programming, Documentation, SOP, User manual, Whitepaper, etc.

LinkedIn

Related Article - Java Loop