-1

I was not able to find a forEach method which calls a lamda with the current object and the current index.

Unfortunately this is not implemented in java8, so following implementation is not possible:

List<String> list = Arrays.asList("one", "two");
list.forEach((element, index) -> System.out.println(String.format("[%d] : %s", index, element)));

I know a simple way to do this is to use the for each loop with a index integer:

List<String> list = Arrays.asList("one", "two");

int index = 0;
for (String element : list) {
   System.out.println(String.format("[%d] : %s", index++, element));
}

I think the common code to init a index intetger and to increment it for each iteration should be moved to a method. So I defined my own forEach method:

public static <T> void forEach(@NonNull Iterable<T> iterable, @NonNull ObjIntConsumer<T> consumer) {
    int i = 0;
    for (T t : iterable) {
        consumer.accept(t, i++);
    }
}

And I can use it like:

List<String> list = Arrays.asList("one", "two");
forEach(list, (element, index) -> System.out.println(String.format("[%d] : %s", index, element)));

I was not able to find a similar implementation in any util library (e.g. guava). So I have following questions:

  • Is there a reason why there is no an utility which provides me this functionality?
  • Is there a reason why this is not implemented in java Iterable.forEach methdod?
  • Is there a good utility I didn't find which provides this functionality?
CodingSamples
  • 194
  • 1
  • 1
  • 7
  • 1
    Does this answer your question? [Is there a concise way to iterate over a stream with indices in Java 8?](https://stackoverflow.com/questions/18552005/is-there-a-concise-way-to-iterate-over-a-stream-with-indices-in-java-8) – Harihar Das Dec 25 '19 at 21:17
  • @HariharDas thank you. I found this https://www.eclipse.org/collections/javadoc/7.0.0/org/eclipse/collections/impl/utility/Iterate.html#forEachWithIndex-java.lang.Iterable-org.eclipse.collections.api.block.procedure.primitive.ObjectIntProcedure- in https://www.eclipse.org/collections/ – CodingSamples Dec 25 '19 at 21:44

2 Answers2

8

If you want to use forEach you can use IntStream like so :

IntStream.range(0, list.size())
        .forEach(index -> System.out.println(String.format("[%d] : %s", index, list.get(index))));
Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
  • I want to iterate over a collection and get the current element and the current index – CodingSamples Dec 25 '19 at 20:57
  • 1
    This is exactly what the code does. Besides, why not simply use a traditional `for`-loop? – Turing85 Dec 25 '19 at 20:59
  • @CodingSamples you can just use : `for (int i = 0; i < list.size(); i++) { System.out.println(String.format("[%d] : %s", i, list.get(i))); }` – Youcef LAIDANI Dec 25 '19 at 20:59
  • 1
    If the list is not a random access list, using a counter as done in the question is a much better idea, though. – JB Nizet Dec 25 '19 at 21:01
  • @JBNizet I think you are right. It s better to avoid the `get` method! So both proposals don't work for me and are also more complex as my solution... I am just asking me why I can't find a proper solution. Is my case so special? I don't think so ... – CodingSamples Dec 25 '19 at 21:14
  • 1
    You find two solutions already. What's the problem with these two solutions. The fact that you didn't find a forEachWithIndex in the JDK is only a sign that the designers of the JDK libraries didn't find it useful or common enough to add it to the standard lib, considering that implementing it yourself or using a simple loop is easy enough. – JB Nizet Dec 25 '19 at 21:22
  • @JBNizet I just was surprised why this is not implemented in the java SDK and I tried to find a common library to solve this issue. To have a clean code. I found this https://www.eclipse.org/collections/javadoc/7.0.0/org/eclipse/collections/impl/utility/Iterate.html#forEachWithIndex-java.lang.Iterable-org.eclipse.collections.api.block.procedure.primitive.ObjectIntProcedure- in the eclipse collection lib. That's exaclty what I want and is very similar to my solution. Thank you =) – CodingSamples Dec 25 '19 at 21:53
2

I found a util method in eclipse collections with this post Is there a concise way to iterate over a stream with indices in Java 8?

https://www.eclipse.org/collections/javadoc/7.0.0/org/eclipse/collections/impl/utility/Iterate.html#forEachWithIndex-java.lang.Iterable-org.eclipse.collections.api.block.procedure.primitive.ObjectIntProcedure-

Iterate.forEachWithIndex(people, (Person person, int index) -> LOGGER.info("Index: " + index + " person: " + person.getName()));

The implementation https://github.com/eclipse/eclipse-collections/blob/master/eclipse-collections/src/main/java/org/eclipse/collections/impl/utility/internal/IteratorIterate.java is very similar to my util method:

public static <T> void forEach(@NonNull Iterable<T> iterable, @NonNull ObjIntConsumer<T> consumer) {
    int i = 0;
    for (T t : iterable) {
        consumer.accept(t, i++);
    }
}
CodingSamples
  • 194
  • 1
  • 1
  • 7