355
votes

When using external iteration over an Iterable we use break or return from enhanced for-each loop as:

for (SomeObject obj : someObjects) {
   if (some_condition_met) {
      break; // or return obj
   }
}

How can we break or return using the internal iteration in a Java 8 lambda expression like:

someObjects.forEach(obj -> {
   //what to do here?
})
14
You can't. Just use a real for statement.Boann
Consider another approach, you just want to not execute code, so, a simple if condition inside the forEach will do the trick.Thomas Decaux

14 Answers

425
votes

If you need this, you shouldn't use forEach, but one of the other methods available on streams; which one, depends on what your goal is.

For example, if the goal of this loop is to find the first element which matches some predicate:

Optional<SomeObject> result =
    someObjects.stream().filter(obj -> some_condition_met).findFirst();

(Note: This will not iterate the whole collection, because streams are lazily evaluated - it will stop at the first object that matches the condition).

If you just want to know if there's an element in the collection for which the condition is true, you could use anyMatch:

boolean result = someObjects.stream().anyMatch(obj -> some_condition_met);
56
votes

This is possible for Iterable.forEach() (but not reliably with Stream.forEach()). The solution is not nice, but it is possible.

WARNING: You should not use it for controlling business logic, but purely for handling an exceptional situation which occurs during the execution of the forEach(). Such as a resource suddenly stops being accessible, one of the processed objects is violating a contract (e.g. contract says that all the elements in the stream must not be null but suddenly and unexpectedly one of them is null) etc.

According to the documentation for Iterable.forEach():

Performs the given action for each element of the Iterable until all elements have been processed or the action throws an exception... Exceptions thrown by the action are relayed to the caller.

So you throw an exception which will immediately break the internal loop.

The code will be something like this - I cannot say I like it but it works. You create your own class BreakException which extends RuntimeException.

try {
    someObjects.forEach(obj -> {
        // some useful code here
        if(some_exceptional_condition_met) {
            throw new BreakException();
       }
    }
}
catch (BreakException e) {
    // here you know that your condition has been met at least once
}

Notice that the try...catch is not around the lambda expression, but rather around the whole forEach() method. To make it more visible, see the following transcription of the code which shows it more clearly:

Consumer<? super SomeObject> action = obj -> {
    // some useful code here
    if(some_exceptional_condition_met) {
        throw new BreakException();
    }
});

try {
    someObjects.forEach(action);
}
catch (BreakException e) {
    // here you know that your condition has been met at least once
}
54
votes

A return in a lambda equals a continue in a for-each, but there is no equivalent to a break. You can just do a return to continue:

someObjects.forEach(obj -> {
   if (some_condition_met) {
      return;
   }
})
25
votes

Below you find the solution I used in a project. Instead forEach just use allMatch:

someObjects.allMatch(obj -> {
    return !some_condition_met;
});
13
votes

Update with Java 9+ with takeWhile:

MutableBoolean ongoing = MutableBoolean.of(true);
someobjects.stream()...takeWhile(t -> ongoing.value()).forEach(t -> {
    // doing something.
    if (...) { // want to break;
        ongoing.setFalse();
    }
});
11
votes

Either you need to use a method which uses a predicate indicating whether to keep going (so it has the break instead) or you need to throw an exception - which is a very ugly approach, of course.

So you could write a forEachConditional method like this:

public static <T> void forEachConditional(Iterable<T> source,
                                          Predicate<T> action) {
    for (T item : source) {
        if (!action.test(item)) {
            break;
        }
    }
}

Rather than Predicate<T>, you might want to define your own functional interface with the same general method (something taking a T and returning a bool) but with names that indicate the expectation more clearly - Predicate<T> isn't ideal here.

9
votes

You can use java8 + rxjava.

//import java.util.stream.IntStream;
//import rx.Observable;

    IntStream intStream  = IntStream.range(1,10000000);
    Observable.from(() -> intStream.iterator())
            .takeWhile(n -> n < 10)
            .forEach(n-> System.out.println(n));
7
votes

For maximal performance in parallel operations use findAny() which is similar to findFirst().

Optional<SomeObject> result =
    someObjects.stream().filter(obj -> some_condition_met).findAny();

However If a stable result is desired, use findFirst() instead.

Also note that matching patterns (anyMatch()/allMatch) will return only boolean, you will not get matched object.

3
votes

I have achieved by something like this

  private void doSomething() {
            List<Action> actions = actionRepository.findAll();
            boolean actionHasFormFields = actions.stream().anyMatch(actionHasMyFieldsPredicate());
            if (actionHasFormFields){
                context.addError(someError);
            }
        }
    }

    private Predicate<Action> actionHasMyFieldsPredicate(){
        return action -> action.getMyField1() != null;
    }
3
votes

You can achieve that using a mix of peek(..) and anyMatch(..).

Using your example:

someObjects.stream().peek(obj -> {
   <your code here>
}).anyMatch(obj -> !<some_condition_met>);

Or just write a generic util method:

public static <T> void streamWhile(Stream<T> stream, Predicate<? super T> predicate, Consumer<? super T> consumer) {
    stream.peek(consumer).anyMatch(predicate.negate());
}

And then use it, like this:

streamWhile(someObjects.stream(), obj -> <some_condition_met>, obj -> {
   <your code here>
});
0
votes

What about this one:

final BooleanWrapper condition = new BooleanWrapper();
someObjects.forEach(obj -> {
   if (condition.ok()) {
     // YOUR CODE to control
     condition.stop();
   }
});

Where BooleanWrapper is a class you must implement to control the flow.

0
votes
int valueToMatch = 7;
Stream.of(1,2,3,4,5,6,7,8).anyMatch(val->{
   boolean isMatch = val == valueToMatch;
   if(isMatch) {
      /*Do whatever you want...*/
       System.out.println(val);
   }
   return isMatch;
});

It will do only operation where it find match, and after find match it stop it's iteration.

0
votes

I would suggest using anyMatch. Example:-

return someObjects.stream().anyMatch(obj -> 
    some_condition_met;
);

You can refer this post for understanding anyMatch:- https://beginnersbook.com/2017/11/java-8-stream-anymatch-example/

0
votes
public static void main(String[] args) {
    List<String> list = Arrays.asList("one", "two", "three", "seven", "nine");
    AtomicBoolean yes = new AtomicBoolean(true);
    list.stream().takeWhile(value -> yes.get()).forEach(value -> {
        System.out.println("prior cond" + value);
        if (value.equals("two")) {
            System.out.println(value);
            yes.set(false);
        }

    });
    //System.out.println("Hello World");
}