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
}
Share:
65,808

Related videos on Youtube

ytoledano
Author by

ytoledano

Updated on June 25, 2020

Comments

  • ytoledano
    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
      fge almost 9 years
      If you use a Stream, why iterate in the first place? Note: your code can be written strings.stream().filter(s -> s.length() == 2).forEach(System.out::println)
    • ytoledano
      ytoledano almost 9 years
      I actually have a big chunk of code processing the element and I don't want to refactor it too much if possible
    • fge
      fge almost 9 years
      Then just don't refactor if it works. Using streams for the sake of using streams is not the way to use streams :p
    • ytoledano
      ytoledano almost 9 years
      You'll have to excuse my C#... there you wouldn't think twice about changing a if (...) continue to a .where(!...) on the IEnumerable
    • Lii
      Lii almost 9 years
      The answer to this question is given in an answer to the question which @TagirValeev links to.
    • glglgl
      glglgl over 8 years
      @fge forEachOrdered might be more appropriate...
    • Sasha
      Sasha over 7 years
    • sfkleach
      sfkleach over 5 years
      @fge because forEach is clumsy and not very readable for anything other than very simple expressions.
    • Oleg Afanasyev
      Oleg Afanasyev almost 3 years
      You can convert a myStream into Iterable as follows for (X x : (Iterable<X>)myStream::iterator) { // do something }. This is helpful when you want to avoid creating an array object.
  • ytoledano
    ytoledano almost 9 years
    Does toArray() copy the elements? I forgot to mention this in the orig question but I'd really prefer not to copy.
  • assylias
    assylias almost 9 years
    @ytoledano yes it would create a new array and copy the element references into the array.
  • ytoledano
    ytoledano almost 9 years
    Thanks, I'm keeping it as it is.
  • assylias
    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
    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 to forEach/collect. Also note that for loop is much easier to debug compared to lambda.
  • assylias
    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
    Vadzim almost 9 years
    Pros and cons of both loop styles: stackoverflow.com/questions/16635398/…
  • PAA
    PAA almost 8 years
    Above code will not work In case of static context - "Cannot use this in a static context"