How do I iterate over a stream in Java using for?
65,808
You need an iterable to be able to use a for-each loop, for example a collection or an array:
for (String s : strings.stream().filter(s->s.length() == 2).toArray(String[]::new)) {
Alternatively, you could completely get rid of the for loop:
strings.stream().filter(s->s.length() == 2).forEach(System.out::println);
You mention you don't want to refactor your for loop but you could extract its body in another method:
strings.stream().filter(s->s.length() == 2).forEach(this::process);
private void process(String s) {
//body of the for loop
}
Related videos on Youtube
Author by
ytoledano
Updated on June 25, 2020Comments
-
ytoledano almost 4 years
I have this code:
List<String> strings = Arrays.asList("a", "b", "cc"); for (String s : strings) { if (s.length() == 2) System.out.println(s); }
I want to write it using a filter and a lambda:
for (String s : strings.stream().filter(s->s.length() == 2)) { System.out.println(s); }
I get
Can only iterate over an array or an instance of java.lang.Iterable
.I try:
for (String s : strings.stream().filter(s->s.length() == 2).iterator()) { System.out.println(s); }
And I get the same error. Is this even possible? I would really prefer not to do stream.forEach() and pass a consumer.
Edit: it's important to me not to copy the elements.
-
fge almost 9 yearsIf you use a
Stream
, why iterate in the first place? Note: your code can be writtenstrings.stream().filter(s -> s.length() == 2).forEach(System.out::println)
-
ytoledano almost 9 yearsI actually have a big chunk of code processing the element and I don't want to refactor it too much if possible
-
fge almost 9 yearsThen just don't refactor if it works. Using streams for the sake of using streams is not the way to use streams :p
-
ytoledano almost 9 yearsYou'll have to excuse my C#... there you wouldn't think twice about changing a
if (...) continue
to a.where(!...)
on the IEnumerable -
Lii almost 9 yearsThe answer to this question is given in an answer to the question which @TagirValeev links to.
-
glglgl over 8 years@fge
forEachOrdered
might be more appropriate... -
Sasha over 7 years
-
sfkleach over 5 years@fge because forEach is clumsy and not very readable for anything other than very simple expressions.
-
Oleg Afanasyev almost 3 yearsYou can convert a
myStream
intoIterable
as followsfor (X x : (Iterable<X>)myStream::iterator) { // do something }
. This is helpful when you want to avoid creating an array object.
-
-
ytoledano almost 9 yearsDoes toArray() copy the elements? I forgot to mention this in the orig question but I'd really prefer not to copy.
-
assylias almost 9 years@ytoledano yes it would create a new array and copy the element references into the array.
-
ytoledano almost 9 yearsThanks, I'm keeping it as it is.
-
assylias almost 9 years@ytoledano You did not give details on the content of the for loop body - there may be better ways depending on what it is...
-
Tagir Valeev almost 9 years@assylias, when refactoring the old code there can be many various things which prevent you from using lambdas like mutable variables or checked exceptions. This can be considered as bad design from the Java-8 point of view, but it's still the code which works and should be supported. Refactoring everything at once might be problematic. I personally saw many
for
loops which may benefit from stream API, but cannot be easily converted toforEach/collect
. Also note thatfor
loop is much easier to debug compared to lambda. -
assylias almost 9 years@TagirValeev certainly - and there are cases where for loops are just easier and more readable. I'm just saying that without knowing what is inside the loop it's difficult to say if streams are a good fit or not.
-
Vadzim almost 9 yearsPros and cons of both loop styles: stackoverflow.com/questions/16635398/…
-
PAA almost 8 yearsAbove code will not work In case of static context - "Cannot use this in a static context"