Java 8 forEach with index
JavaFor LoopForeachJava 8Java Problem Overview
Is there a way to build a forEach
method in Java 8 that iterates with an index? Ideally I'd like something like this:
params.forEach((idx, e) -> query.bind(idx, e));
The best I could do right now is:
int idx = 0;
params.forEach(e -> {
query.bind(idx, e);
idx++;
});
Java Solutions
Solution 1 - Java
Since you are iterating over an indexable collection (lists, etc.), I presume that you can then just iterate with the indices of the elements:
IntStream.range(0, params.size())
.forEach(idx ->
query.bind(
idx,
params.get(idx)
)
)
;
The resulting code is similar to iterating a list with the classic i++-style for loop, except with easier parallelizability (assuming, of course, that concurrent read-only access to params is safe).
Solution 2 - Java
It works with params if you capture an array with one element, that holds the current index.
int[] idx = { 0 };
params.forEach(e -> query.bind(idx[0]++, e));
The above code assumes, that the method forEach iterates through the elements in encounter order. The interface Iterable specifies this behaviour for all classes unless otherwise documented. Apparently it works for all implementations of Iterable from the standard library, and changing this behaviour in the future would break backward-compatibility.
If you are working with Streams instead of Collections/Iterables, you should use forEachOrdered, because forEach can be executed concurrently and the elements can occur in different order. The following code works for both sequential and parallel streams:
int[] idx = { 0 };
params.stream().forEachOrdered(e -> query.bind(idx[0]++, e));
Solution 3 - Java
There are workarounds but no clean/short/sweet way to do it with streams and to be honest, you would probably be better off with:
int idx = 0;
for (Param p : params) query.bind(idx++, p);
Or the older style:
for (int idx = 0; idx < params.size(); idx++) query.bind(idx, params.get(idx));