Java 8 forEach with index [duplicate]











up vote
102
down vote

favorite
16













This question already has an answer here:




  • Is there a concise way to iterate over a stream with indices in Java 8?

    17 answers




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++;
});









share|improve this question















marked as duplicate by Sotirios Delimanolis, assylias, JimmyB, Jeff Lambert, Patrick Hofman Apr 1 '14 at 20:22


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.











  • 2




    one line shorter if you merge the increment query.bind(idx++, e); but that's all I can think of
    – zapl
    Apr 1 '14 at 17:42






  • 11




    Also, you shouldn't be able to modify idx within that lambda.
    – Sotirios Delimanolis
    Apr 1 '14 at 17:49












  • @SotiriosDelimanolis it actually compiles
    – Josh Stone
    Apr 1 '14 at 17:58










  • It would if idx is an instance variable or something. It will not if the code you posted is in a method/constructor body.
    – Sotirios Delimanolis
    Apr 1 '14 at 17:59






  • 2




    @assylias I am voting to reopen this question because I don't think it is an exact duplicate of the linked question. The poster of the linked question wanted to get access to the index in the middle of stream processing, while the focus of this question is just to get the index in the (terminal) forEach method (basically to replace the traditional for loop in which index is manipulated manually). I think that we should not prevent more answers to be added here. Actually I would like to contribute with an answer which is suitable to this question, but not to the linked question.
    – Dragan Bozanovic
    Feb 18 '16 at 17:14















up vote
102
down vote

favorite
16













This question already has an answer here:




  • Is there a concise way to iterate over a stream with indices in Java 8?

    17 answers




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++;
});









share|improve this question















marked as duplicate by Sotirios Delimanolis, assylias, JimmyB, Jeff Lambert, Patrick Hofman Apr 1 '14 at 20:22


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.











  • 2




    one line shorter if you merge the increment query.bind(idx++, e); but that's all I can think of
    – zapl
    Apr 1 '14 at 17:42






  • 11




    Also, you shouldn't be able to modify idx within that lambda.
    – Sotirios Delimanolis
    Apr 1 '14 at 17:49












  • @SotiriosDelimanolis it actually compiles
    – Josh Stone
    Apr 1 '14 at 17:58










  • It would if idx is an instance variable or something. It will not if the code you posted is in a method/constructor body.
    – Sotirios Delimanolis
    Apr 1 '14 at 17:59






  • 2




    @assylias I am voting to reopen this question because I don't think it is an exact duplicate of the linked question. The poster of the linked question wanted to get access to the index in the middle of stream processing, while the focus of this question is just to get the index in the (terminal) forEach method (basically to replace the traditional for loop in which index is manipulated manually). I think that we should not prevent more answers to be added here. Actually I would like to contribute with an answer which is suitable to this question, but not to the linked question.
    – Dragan Bozanovic
    Feb 18 '16 at 17:14













up vote
102
down vote

favorite
16









up vote
102
down vote

favorite
16






16






This question already has an answer here:




  • Is there a concise way to iterate over a stream with indices in Java 8?

    17 answers




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++;
});









share|improve this question
















This question already has an answer here:




  • Is there a concise way to iterate over a stream with indices in Java 8?

    17 answers




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++;
});




This question already has an answer here:




  • Is there a concise way to iterate over a stream with indices in Java 8?

    17 answers








java for-loop foreach java-8






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 18 '16 at 17:07









Dragan Bozanovic

18k22379




18k22379










asked Apr 1 '14 at 17:40









Josh Stone

1,08841528




1,08841528




marked as duplicate by Sotirios Delimanolis, assylias, JimmyB, Jeff Lambert, Patrick Hofman Apr 1 '14 at 20:22


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.






marked as duplicate by Sotirios Delimanolis, assylias, JimmyB, Jeff Lambert, Patrick Hofman Apr 1 '14 at 20:22


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.










  • 2




    one line shorter if you merge the increment query.bind(idx++, e); but that's all I can think of
    – zapl
    Apr 1 '14 at 17:42






  • 11




    Also, you shouldn't be able to modify idx within that lambda.
    – Sotirios Delimanolis
    Apr 1 '14 at 17:49












  • @SotiriosDelimanolis it actually compiles
    – Josh Stone
    Apr 1 '14 at 17:58










  • It would if idx is an instance variable or something. It will not if the code you posted is in a method/constructor body.
    – Sotirios Delimanolis
    Apr 1 '14 at 17:59






  • 2




    @assylias I am voting to reopen this question because I don't think it is an exact duplicate of the linked question. The poster of the linked question wanted to get access to the index in the middle of stream processing, while the focus of this question is just to get the index in the (terminal) forEach method (basically to replace the traditional for loop in which index is manipulated manually). I think that we should not prevent more answers to be added here. Actually I would like to contribute with an answer which is suitable to this question, but not to the linked question.
    – Dragan Bozanovic
    Feb 18 '16 at 17:14














  • 2




    one line shorter if you merge the increment query.bind(idx++, e); but that's all I can think of
    – zapl
    Apr 1 '14 at 17:42






  • 11




    Also, you shouldn't be able to modify idx within that lambda.
    – Sotirios Delimanolis
    Apr 1 '14 at 17:49












  • @SotiriosDelimanolis it actually compiles
    – Josh Stone
    Apr 1 '14 at 17:58










  • It would if idx is an instance variable or something. It will not if the code you posted is in a method/constructor body.
    – Sotirios Delimanolis
    Apr 1 '14 at 17:59






  • 2




    @assylias I am voting to reopen this question because I don't think it is an exact duplicate of the linked question. The poster of the linked question wanted to get access to the index in the middle of stream processing, while the focus of this question is just to get the index in the (terminal) forEach method (basically to replace the traditional for loop in which index is manipulated manually). I think that we should not prevent more answers to be added here. Actually I would like to contribute with an answer which is suitable to this question, but not to the linked question.
    – Dragan Bozanovic
    Feb 18 '16 at 17:14








2




2




one line shorter if you merge the increment query.bind(idx++, e); but that's all I can think of
– zapl
Apr 1 '14 at 17:42




one line shorter if you merge the increment query.bind(idx++, e); but that's all I can think of
– zapl
Apr 1 '14 at 17:42




11




11




Also, you shouldn't be able to modify idx within that lambda.
– Sotirios Delimanolis
Apr 1 '14 at 17:49






Also, you shouldn't be able to modify idx within that lambda.
– Sotirios Delimanolis
Apr 1 '14 at 17:49














@SotiriosDelimanolis it actually compiles
– Josh Stone
Apr 1 '14 at 17:58




@SotiriosDelimanolis it actually compiles
– Josh Stone
Apr 1 '14 at 17:58












It would if idx is an instance variable or something. It will not if the code you posted is in a method/constructor body.
– Sotirios Delimanolis
Apr 1 '14 at 17:59




It would if idx is an instance variable or something. It will not if the code you posted is in a method/constructor body.
– Sotirios Delimanolis
Apr 1 '14 at 17:59




2




2




@assylias I am voting to reopen this question because I don't think it is an exact duplicate of the linked question. The poster of the linked question wanted to get access to the index in the middle of stream processing, while the focus of this question is just to get the index in the (terminal) forEach method (basically to replace the traditional for loop in which index is manipulated manually). I think that we should not prevent more answers to be added here. Actually I would like to contribute with an answer which is suitable to this question, but not to the linked question.
– Dragan Bozanovic
Feb 18 '16 at 17:14




@assylias I am voting to reopen this question because I don't think it is an exact duplicate of the linked question. The poster of the linked question wanted to get access to the index in the middle of stream processing, while the focus of this question is just to get the index in the (terminal) forEach method (basically to replace the traditional for loop in which index is manipulated manually). I think that we should not prevent more answers to be added here. Actually I would like to contribute with an answer which is suitable to this question, but not to the linked question.
– Dragan Bozanovic
Feb 18 '16 at 17:14












3 Answers
3






active

oldest

votes

















up vote
118
down vote



accepted










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).






share|improve this answer

















  • 1




    Very nice. This works well for my case.
    – Josh Stone
    Apr 1 '14 at 19:06










  • Would this work in case you want specific order for params (e.g. sorted)?
    – Tomer Cagan
    Jun 4 '16 at 11:49






  • 1




    @TomerCagan You may either: map the indices to the preferred order, if said order can be expressed as a function (to iterate the params in reverse, use IntStream.range(0, params.size()).map(i -> params.size() - 1 - i)), or just provide your own range if the specific order is not something that can be mathematically derived from the result of IntStream.range(0, params.size()), like Stream.iterate(new int {0, 1}, ia -> new int {ia[1], ia[0] + ia[1]}).mapToInt(ia -> ia[0]).filter(i -> i < params.size()).limit(params.size()) if you want to iterate a subset of the params in Fibonacci order.
    – srborlongan
    Jun 4 '16 at 12:27








  • 3




    the only consideration is that when you are iterating a LinkedList in this way you are going to have O(nˆ2) instead of O(n)
    – Bauna
    May 19 '17 at 13:26






  • 4




    Once again, Java and its terrible syntax for simple things.
    – AFP_555
    Nov 4 '17 at 6:38


















up vote
53
down vote













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));





share|improve this answer



















  • 3




    Rather than using an int array it's best to use an AtomicInteger. This will also ensure that if the elements are encountered out of order we at least get a unique index for each element.
    – Brett Ryan
    Sep 29 '15 at 0:46






  • 1




    @BrettRyan: I do not agree. AtomicInteger expresses the wrong intent, it is less efficient, and the sequential execution is guaranteed in this case.
    – nosid
    Sep 29 '15 at 18:18










  • Wouldn't MutableInt in apache lang library work well? It doesn't need to be a synchronized structure if using forEachOrdered, am I right?
    – Skychan
    Oct 16 '15 at 15:24










  • @Skychan: MutableInt doesn't help in this situation because it lacks some operations. In particular something like getAndIncrement.
    – nosid
    Oct 18 '15 at 11:07








  • 2




    @nosid I don't think using an int is more intent revealing than AtomicInteger. And if performance is a concern, perhaps a for loop is better as it avoids the Stream machinery which probably dwarfs the highly optimized Atomic* classes.
    – btiernay
    Nov 5 '16 at 14:07


















up vote
21
down vote













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);





share|improve this answer





















  • Late but fully agree. Plain old for loop is sufficient when index is required.
    – Vortex
    Oct 8 '17 at 2:47










  • @Vortex And more readable.
    – AFP_555
    Nov 4 '17 at 6:45


















3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
118
down vote



accepted










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).






share|improve this answer

















  • 1




    Very nice. This works well for my case.
    – Josh Stone
    Apr 1 '14 at 19:06










  • Would this work in case you want specific order for params (e.g. sorted)?
    – Tomer Cagan
    Jun 4 '16 at 11:49






  • 1




    @TomerCagan You may either: map the indices to the preferred order, if said order can be expressed as a function (to iterate the params in reverse, use IntStream.range(0, params.size()).map(i -> params.size() - 1 - i)), or just provide your own range if the specific order is not something that can be mathematically derived from the result of IntStream.range(0, params.size()), like Stream.iterate(new int {0, 1}, ia -> new int {ia[1], ia[0] + ia[1]}).mapToInt(ia -> ia[0]).filter(i -> i < params.size()).limit(params.size()) if you want to iterate a subset of the params in Fibonacci order.
    – srborlongan
    Jun 4 '16 at 12:27








  • 3




    the only consideration is that when you are iterating a LinkedList in this way you are going to have O(nˆ2) instead of O(n)
    – Bauna
    May 19 '17 at 13:26






  • 4




    Once again, Java and its terrible syntax for simple things.
    – AFP_555
    Nov 4 '17 at 6:38















up vote
118
down vote



accepted










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).






share|improve this answer

















  • 1




    Very nice. This works well for my case.
    – Josh Stone
    Apr 1 '14 at 19:06










  • Would this work in case you want specific order for params (e.g. sorted)?
    – Tomer Cagan
    Jun 4 '16 at 11:49






  • 1




    @TomerCagan You may either: map the indices to the preferred order, if said order can be expressed as a function (to iterate the params in reverse, use IntStream.range(0, params.size()).map(i -> params.size() - 1 - i)), or just provide your own range if the specific order is not something that can be mathematically derived from the result of IntStream.range(0, params.size()), like Stream.iterate(new int {0, 1}, ia -> new int {ia[1], ia[0] + ia[1]}).mapToInt(ia -> ia[0]).filter(i -> i < params.size()).limit(params.size()) if you want to iterate a subset of the params in Fibonacci order.
    – srborlongan
    Jun 4 '16 at 12:27








  • 3




    the only consideration is that when you are iterating a LinkedList in this way you are going to have O(nˆ2) instead of O(n)
    – Bauna
    May 19 '17 at 13:26






  • 4




    Once again, Java and its terrible syntax for simple things.
    – AFP_555
    Nov 4 '17 at 6:38













up vote
118
down vote



accepted







up vote
118
down vote



accepted






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).






share|improve this answer












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).







share|improve this answer












share|improve this answer



share|improve this answer










answered Apr 1 '14 at 17:57









srborlongan

2,95831823




2,95831823








  • 1




    Very nice. This works well for my case.
    – Josh Stone
    Apr 1 '14 at 19:06










  • Would this work in case you want specific order for params (e.g. sorted)?
    – Tomer Cagan
    Jun 4 '16 at 11:49






  • 1




    @TomerCagan You may either: map the indices to the preferred order, if said order can be expressed as a function (to iterate the params in reverse, use IntStream.range(0, params.size()).map(i -> params.size() - 1 - i)), or just provide your own range if the specific order is not something that can be mathematically derived from the result of IntStream.range(0, params.size()), like Stream.iterate(new int {0, 1}, ia -> new int {ia[1], ia[0] + ia[1]}).mapToInt(ia -> ia[0]).filter(i -> i < params.size()).limit(params.size()) if you want to iterate a subset of the params in Fibonacci order.
    – srborlongan
    Jun 4 '16 at 12:27








  • 3




    the only consideration is that when you are iterating a LinkedList in this way you are going to have O(nˆ2) instead of O(n)
    – Bauna
    May 19 '17 at 13:26






  • 4




    Once again, Java and its terrible syntax for simple things.
    – AFP_555
    Nov 4 '17 at 6:38














  • 1




    Very nice. This works well for my case.
    – Josh Stone
    Apr 1 '14 at 19:06










  • Would this work in case you want specific order for params (e.g. sorted)?
    – Tomer Cagan
    Jun 4 '16 at 11:49






  • 1




    @TomerCagan You may either: map the indices to the preferred order, if said order can be expressed as a function (to iterate the params in reverse, use IntStream.range(0, params.size()).map(i -> params.size() - 1 - i)), or just provide your own range if the specific order is not something that can be mathematically derived from the result of IntStream.range(0, params.size()), like Stream.iterate(new int {0, 1}, ia -> new int {ia[1], ia[0] + ia[1]}).mapToInt(ia -> ia[0]).filter(i -> i < params.size()).limit(params.size()) if you want to iterate a subset of the params in Fibonacci order.
    – srborlongan
    Jun 4 '16 at 12:27








  • 3




    the only consideration is that when you are iterating a LinkedList in this way you are going to have O(nˆ2) instead of O(n)
    – Bauna
    May 19 '17 at 13:26






  • 4




    Once again, Java and its terrible syntax for simple things.
    – AFP_555
    Nov 4 '17 at 6:38








1




1




Very nice. This works well for my case.
– Josh Stone
Apr 1 '14 at 19:06




Very nice. This works well for my case.
– Josh Stone
Apr 1 '14 at 19:06












Would this work in case you want specific order for params (e.g. sorted)?
– Tomer Cagan
Jun 4 '16 at 11:49




Would this work in case you want specific order for params (e.g. sorted)?
– Tomer Cagan
Jun 4 '16 at 11:49




1




1




@TomerCagan You may either: map the indices to the preferred order, if said order can be expressed as a function (to iterate the params in reverse, use IntStream.range(0, params.size()).map(i -> params.size() - 1 - i)), or just provide your own range if the specific order is not something that can be mathematically derived from the result of IntStream.range(0, params.size()), like Stream.iterate(new int {0, 1}, ia -> new int {ia[1], ia[0] + ia[1]}).mapToInt(ia -> ia[0]).filter(i -> i < params.size()).limit(params.size()) if you want to iterate a subset of the params in Fibonacci order.
– srborlongan
Jun 4 '16 at 12:27






@TomerCagan You may either: map the indices to the preferred order, if said order can be expressed as a function (to iterate the params in reverse, use IntStream.range(0, params.size()).map(i -> params.size() - 1 - i)), or just provide your own range if the specific order is not something that can be mathematically derived from the result of IntStream.range(0, params.size()), like Stream.iterate(new int {0, 1}, ia -> new int {ia[1], ia[0] + ia[1]}).mapToInt(ia -> ia[0]).filter(i -> i < params.size()).limit(params.size()) if you want to iterate a subset of the params in Fibonacci order.
– srborlongan
Jun 4 '16 at 12:27






3




3




the only consideration is that when you are iterating a LinkedList in this way you are going to have O(nˆ2) instead of O(n)
– Bauna
May 19 '17 at 13:26




the only consideration is that when you are iterating a LinkedList in this way you are going to have O(nˆ2) instead of O(n)
– Bauna
May 19 '17 at 13:26




4




4




Once again, Java and its terrible syntax for simple things.
– AFP_555
Nov 4 '17 at 6:38




Once again, Java and its terrible syntax for simple things.
– AFP_555
Nov 4 '17 at 6:38












up vote
53
down vote













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));





share|improve this answer



















  • 3




    Rather than using an int array it's best to use an AtomicInteger. This will also ensure that if the elements are encountered out of order we at least get a unique index for each element.
    – Brett Ryan
    Sep 29 '15 at 0:46






  • 1




    @BrettRyan: I do not agree. AtomicInteger expresses the wrong intent, it is less efficient, and the sequential execution is guaranteed in this case.
    – nosid
    Sep 29 '15 at 18:18










  • Wouldn't MutableInt in apache lang library work well? It doesn't need to be a synchronized structure if using forEachOrdered, am I right?
    – Skychan
    Oct 16 '15 at 15:24










  • @Skychan: MutableInt doesn't help in this situation because it lacks some operations. In particular something like getAndIncrement.
    – nosid
    Oct 18 '15 at 11:07








  • 2




    @nosid I don't think using an int is more intent revealing than AtomicInteger. And if performance is a concern, perhaps a for loop is better as it avoids the Stream machinery which probably dwarfs the highly optimized Atomic* classes.
    – btiernay
    Nov 5 '16 at 14:07















up vote
53
down vote













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));





share|improve this answer



















  • 3




    Rather than using an int array it's best to use an AtomicInteger. This will also ensure that if the elements are encountered out of order we at least get a unique index for each element.
    – Brett Ryan
    Sep 29 '15 at 0:46






  • 1




    @BrettRyan: I do not agree. AtomicInteger expresses the wrong intent, it is less efficient, and the sequential execution is guaranteed in this case.
    – nosid
    Sep 29 '15 at 18:18










  • Wouldn't MutableInt in apache lang library work well? It doesn't need to be a synchronized structure if using forEachOrdered, am I right?
    – Skychan
    Oct 16 '15 at 15:24










  • @Skychan: MutableInt doesn't help in this situation because it lacks some operations. In particular something like getAndIncrement.
    – nosid
    Oct 18 '15 at 11:07








  • 2




    @nosid I don't think using an int is more intent revealing than AtomicInteger. And if performance is a concern, perhaps a for loop is better as it avoids the Stream machinery which probably dwarfs the highly optimized Atomic* classes.
    – btiernay
    Nov 5 '16 at 14:07













up vote
53
down vote










up vote
53
down vote









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));





share|improve this answer














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));






share|improve this answer














share|improve this answer



share|improve this answer








edited Oct 2 at 7:34

























answered Apr 1 '14 at 17:45









nosid

38k785124




38k785124








  • 3




    Rather than using an int array it's best to use an AtomicInteger. This will also ensure that if the elements are encountered out of order we at least get a unique index for each element.
    – Brett Ryan
    Sep 29 '15 at 0:46






  • 1




    @BrettRyan: I do not agree. AtomicInteger expresses the wrong intent, it is less efficient, and the sequential execution is guaranteed in this case.
    – nosid
    Sep 29 '15 at 18:18










  • Wouldn't MutableInt in apache lang library work well? It doesn't need to be a synchronized structure if using forEachOrdered, am I right?
    – Skychan
    Oct 16 '15 at 15:24










  • @Skychan: MutableInt doesn't help in this situation because it lacks some operations. In particular something like getAndIncrement.
    – nosid
    Oct 18 '15 at 11:07








  • 2




    @nosid I don't think using an int is more intent revealing than AtomicInteger. And if performance is a concern, perhaps a for loop is better as it avoids the Stream machinery which probably dwarfs the highly optimized Atomic* classes.
    – btiernay
    Nov 5 '16 at 14:07














  • 3




    Rather than using an int array it's best to use an AtomicInteger. This will also ensure that if the elements are encountered out of order we at least get a unique index for each element.
    – Brett Ryan
    Sep 29 '15 at 0:46






  • 1




    @BrettRyan: I do not agree. AtomicInteger expresses the wrong intent, it is less efficient, and the sequential execution is guaranteed in this case.
    – nosid
    Sep 29 '15 at 18:18










  • Wouldn't MutableInt in apache lang library work well? It doesn't need to be a synchronized structure if using forEachOrdered, am I right?
    – Skychan
    Oct 16 '15 at 15:24










  • @Skychan: MutableInt doesn't help in this situation because it lacks some operations. In particular something like getAndIncrement.
    – nosid
    Oct 18 '15 at 11:07








  • 2




    @nosid I don't think using an int is more intent revealing than AtomicInteger. And if performance is a concern, perhaps a for loop is better as it avoids the Stream machinery which probably dwarfs the highly optimized Atomic* classes.
    – btiernay
    Nov 5 '16 at 14:07








3




3




Rather than using an int array it's best to use an AtomicInteger. This will also ensure that if the elements are encountered out of order we at least get a unique index for each element.
– Brett Ryan
Sep 29 '15 at 0:46




Rather than using an int array it's best to use an AtomicInteger. This will also ensure that if the elements are encountered out of order we at least get a unique index for each element.
– Brett Ryan
Sep 29 '15 at 0:46




1




1




@BrettRyan: I do not agree. AtomicInteger expresses the wrong intent, it is less efficient, and the sequential execution is guaranteed in this case.
– nosid
Sep 29 '15 at 18:18




@BrettRyan: I do not agree. AtomicInteger expresses the wrong intent, it is less efficient, and the sequential execution is guaranteed in this case.
– nosid
Sep 29 '15 at 18:18












Wouldn't MutableInt in apache lang library work well? It doesn't need to be a synchronized structure if using forEachOrdered, am I right?
– Skychan
Oct 16 '15 at 15:24




Wouldn't MutableInt in apache lang library work well? It doesn't need to be a synchronized structure if using forEachOrdered, am I right?
– Skychan
Oct 16 '15 at 15:24












@Skychan: MutableInt doesn't help in this situation because it lacks some operations. In particular something like getAndIncrement.
– nosid
Oct 18 '15 at 11:07






@Skychan: MutableInt doesn't help in this situation because it lacks some operations. In particular something like getAndIncrement.
– nosid
Oct 18 '15 at 11:07






2




2




@nosid I don't think using an int is more intent revealing than AtomicInteger. And if performance is a concern, perhaps a for loop is better as it avoids the Stream machinery which probably dwarfs the highly optimized Atomic* classes.
– btiernay
Nov 5 '16 at 14:07




@nosid I don't think using an int is more intent revealing than AtomicInteger. And if performance is a concern, perhaps a for loop is better as it avoids the Stream machinery which probably dwarfs the highly optimized Atomic* classes.
– btiernay
Nov 5 '16 at 14:07










up vote
21
down vote













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);





share|improve this answer





















  • Late but fully agree. Plain old for loop is sufficient when index is required.
    – Vortex
    Oct 8 '17 at 2:47










  • @Vortex And more readable.
    – AFP_555
    Nov 4 '17 at 6:45















up vote
21
down vote













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);





share|improve this answer





















  • Late but fully agree. Plain old for loop is sufficient when index is required.
    – Vortex
    Oct 8 '17 at 2:47










  • @Vortex And more readable.
    – AFP_555
    Nov 4 '17 at 6:45













up vote
21
down vote










up vote
21
down vote









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);





share|improve this answer












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);






share|improve this answer












share|improve this answer



share|improve this answer










answered Apr 1 '14 at 17:45









assylias

242k48505645




242k48505645












  • Late but fully agree. Plain old for loop is sufficient when index is required.
    – Vortex
    Oct 8 '17 at 2:47










  • @Vortex And more readable.
    – AFP_555
    Nov 4 '17 at 6:45


















  • Late but fully agree. Plain old for loop is sufficient when index is required.
    – Vortex
    Oct 8 '17 at 2:47










  • @Vortex And more readable.
    – AFP_555
    Nov 4 '17 at 6:45
















Late but fully agree. Plain old for loop is sufficient when index is required.
– Vortex
Oct 8 '17 at 2:47




Late but fully agree. Plain old for loop is sufficient when index is required.
– Vortex
Oct 8 '17 at 2:47












@Vortex And more readable.
– AFP_555
Nov 4 '17 at 6:45




@Vortex And more readable.
– AFP_555
Nov 4 '17 at 6:45



Popular posts from this blog

Trompette piccolo

Slow SSRS Report in dynamic grouping and multiple parameters

Simon Yates (cyclisme)