425 Stimmen

Unterbrechen oder zurückkehren vom Java 8 Stream forEach ?

Beim Verwenden einer externen Iteration über ein Iterable verwenden wir break oder return aus einer verbesserten for-each-Schleife wie folgt:

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

Wie können wir mit der internen Iteration in einem Java 8 Lambda-Ausdruck break oder return verwenden wie:

someObjects.forEach(obj -> {
   //was soll hier getan werden?
})

13voto

Jon Skeet Punkte 1325502

Entweder Sie müssen eine Methode verwenden, die einen Prädikator verwendet, der angibt, ob weitergemacht werden soll (also enthält sie anstelle von break) oder Sie müssen eine Ausnahme werfen - was natürlich ein sehr hässlicher Ansatz ist.

Also könnten Sie eine forEachConditional-Methode wie folgt schreiben:

public static  void forEachConditional(Iterable source,
                                          Prädikat aktion) {
    for (T element : quelle) {
        wenn (!aktion.test(element)) {
            break;
        }
    }
}

Statt Prädikat möchten Sie vielleicht Ihr eigenes funktionales Interface mit der gleichen allgemeinen Methode definieren (etwas, das ein T entgegennimmt und einen bool zurückgibt), aber mit Namen, die die Erwartung klarer anzeigen - Prädikat ist hier nicht ideal.

10voto

frhack Punkte 4410

Sie können java8 + rxjava verwenden.

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

7voto

Kanagavelu Sugumar Punkte 17711

Für maximale Leistung bei parallelen Operationen verwenden Sie findAny(), das ähnlich wie findFirst() ist.

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

Wenn jedoch ein stabiles Ergebnis gewünscht wird, verwenden Sie stattdessen findFirst().

Beachten Sie auch, dass Übereinstimmungsmuster (anyMatch() / allMatch) nur einen booleschen Wert zurückgeben, der übereinstimmende Objekt wird nicht zurückgegeben.

6voto

public static void main(String[] args) {
    List 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("Hallo Welt");
}

3voto

Mohammad Adnan Punkte 6217

Ich habe dies ungefähr wie folgt erreicht

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

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X