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?
})

479voto

Jesper Punkte 193903

Wenn Sie dies benötigen, sollten Sie forEach nicht verwenden, sondern eine der anderen Methoden, die auf Streams verfügbar sind; welche Methode, hängt davon ab, was Ihr Ziel ist.

Zum Beispiel, wenn das Ziel dieser Schleife ist, das erste Element zu finden, das einer bestimmten Prädiktion entspricht:

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

(Hinweis: Dies wird nicht die gesamte Sammlung durchlaufen, da Streams träge evaluiert werden - es wird bei dem ersten Objekt, das die Bedingung erfüllt, stehen bleiben).

Wenn Sie nur wissen möchten, ob es ein Element in der Sammlung gibt, für das die Bedingung wahr ist, könnten Sie anyMatch verwenden:

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

85voto

Aneesh Vijendran Punkte 3692

Ein return in einer Lambda entspricht einem continue in einem for-each, aber es gibt kein Äquivalent zu einem break. Du kannst einfach ein return verwenden, um fortzufahren:

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

59voto

Honza Zidek Punkte 8069

Dies ist möglich für Iterable.forEach() (aber nicht zuverlässig mit Stream.forEach()). Die Lösung ist nicht schön, aber es ist möglich.

WARNUNG: Sie sollten es nicht zur Steuerung der Geschäftslogik verwenden, sondern rein für den Umgang mit einer Ausnahmesituation, die während der Ausführung des forEach() auftritt. Zum Beispiel wenn plötzlich ein Ressource nicht mehr erreichbar ist, eines der verarbeiteten Objekte einen Vertrag verletzt (z.B. der Vertrag besagt, dass alle Elemente im Stream nicht null sein dürfen, aber plötzlich und unerwartet ist eines davon null) usw.

Laut der Dokumentation für Iterable.forEach():

Führt die gegebene Aktion für jedes Element des Iterable aus, bis alle Elemente verarbeitet wurden oder die Aktion eine Ausnahme auslöst... Ausnahmen, die von der Aktion ausgelöst werden, werden an den Aufrufer weitergeleitet.

Sie werfen also eine Ausnahme, die sofort die interne Schleife abbricht.

Der Code wird etwas wie folgt sein - Ich kann nicht sagen, dass ich es mag, aber es funktioniert. Sie erstellen Ihre eigene Klasse BreakException, die RuntimeException erweitert.

try {
    someObjects.forEach(obj -> {
        // hier steht nützlicher Code
        if(eine_ausnahmsbedingung_erfüllt) {
            throw new BreakException();
       }
    }
}
catch (BreakException e) {
    // hier wissen Sie, dass Ihre Bedingung mindestens einmal erfüllt wurde
}

Beachten Sie, dass das try...catch nicht um den Lambda-Ausdruck herum steht, sondern vielmehr um die gesamte forEach()-Methode. Um es deutlicher zu machen, sehen Sie sich die folgende Transkription des Codes an, die es klarer zeigt:

Consumer action = obj -> {
    // hier steht nützlicher Code
    if(eine_ausnahmsbedingung_erfüllt) {
        throw new BreakException();
    }
});

try {
    someObjects.forEach(action);
}
catch (BreakException e) {
    // hier wissen Sie, dass Ihre Bedingung mindestens einmal erfüllt wurde
}

31voto

Julian Pieles Punkte 3720

Unten finden Sie die Lösung, die ich in einem Projekt verwendet habe. Verwenden Sie anstelle von forEach einfach allMatch:

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

25voto

user_3380739 Punkte 1495

Aktualisierung mit Java 9+ mit takeWhile:

MutableBoolean ongoing = MutableBoolean.of(true);
someobjects.stream()...takeWhile(t -> ongoing.value()).forEach(t -> {
    // etwas tun.
    if (...) { // unterbrechen möchte;
        ongoing.setFalse();
    }
});

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