Wie kann ich mithilfe eines Lambda-Ausdrucks überprüfen, ob ein Element vorhanden ist?

118

Insbesondere habe ich TabPane und möchte wissen, ob es ein Element mit einer bestimmten ID enthält.

Also möchte ich dies mit Lambda-Ausdruck in Java tun:

boolean idExists = false;
String idToCheck = "someId";

for (Tab t : tabPane.getTabs()){
    if(t.getId().equals(idToCheck)) {
        idExists = true;
    }
}
Miljac
quelle

Antworten:

273

Versuchen Sie, anyMatchLambda Expression zu verwenden. Es ist viel besser Ansatz.

 boolean idExists = tabPane.getTabs().stream()
            .anyMatch(t -> t.getId().equals(idToCheck));
Masudul
quelle
11
Auch erwähnenswert: Wenn Sie die Kontroll Verwendung negieren wollen noneMatchstatt anyMatch.
Schwarzlicht
Aufruf erfordert API-Level 24
FabioLux
50

Während die akzeptierte Antwort korrekt ist, werde ich (meiner Meinung nach) eine elegantere Version hinzufügen:

boolean idExists = tabPane.getTabs().stream()
    .map(Tab::getId)
    .anyMatch(idToCheck::equals);

Vernachlässigen Sie nicht die Verwendung von Stream # map () , mit der die Datenstruktur vor dem Anwenden von reduziert werden kann Predicate.

jFrenetic
quelle
3
was ist hier besser Ich sehe nur noch eine Operation. Tut mir leid, dass ich neu in dieser Lamba-Sache bin.
TecHunter
2
@TecHunter ist es expliziter. Stellen Sie sich vor, Sie lesen diesen Code zum ersten Mal oder nach einer Weile erneut. Es gibt mehrere Vorteile: Erstens zeigen wir sofort, dass wir nicht wirklich an der Registerkarte interessiert sind, sondern an einer Zuordnung davon. Zweitens zeigen wir durch die Verwendung von Methodenreferenzen (was nur möglich ist, weil wir das anfängliche Lambda in zwei Schritte aufteilen), dass im Code keine Überraschungen verborgen sind. Drittens erstellen wir mithilfe von Methodenreferenzen kein neues Prädikat, sondern verwenden es nur wieder equals. Das Beispiel hier ist zwar sehr einfach, aber ich hoffe, Sie verstehen, was ich meine.
Malte Hartwig
@MalteHartwig danke! Ja, ich bekomme deine 3 Punkte, aber ich habe nach der Abflachung gefragt map, es macht einen weiteren Verarbeitungsschritt, nein? Ich werde versuchen, die 2 Methoden zu vergleichen :)
TecHunter
1
@MalteHartwig wurde in einer 10kk ArrayList mit einem einfachen Objekt getestet, das versucht, das letzte Element zu finden. gibt eine 2ms Differenz 131ms gegen 133ms für Ihre. Auf einem 1kk-Array listen Sie Ihre auf, wenn Sie um 2 ms (55 ms bis 53 ms) schneller sind. Also können wir sagen, dass deins besser ist :)
TecHunter
2
@ TechHunter Getter sind supergünstig. Ziehen Sie die Klarheit des Codes immer der Einsparung von zusätzlichen 2 Millisekunden vor (obwohl ich bezweifle, dass die Ergebnisse korrekt sind, kann sie bei jedem Lauf schwanken). Denken Sie außerdem daran, dass Zwischenoperationen an Streams (wie z. B. map) von Natur aus faul sind . Das bedeutet, dass die getIdMethode nicht auf jedes Element der Sammlung angewendet wird. Es ist träge , bis ausgewertet anyMatchkehrt wahr .
jFrenetic
3

Für die obigen Antworten müssen Sie ein neues Stream-Objekt mallocieren.

public <T>
boolean containsByLambda(Collection<? extends T> c, Predicate<? super T> p) {

    for (final T z : c) {
        if (p.test(z)) {
            return true;
        }
    }
    return false;
}

public boolean containsTabById(TabPane tabPane, String id) {
    return containsByLambda(tabPane.getTabs(), z -> z.getId().equals(id));
}
...
if (containsTabById(tabPane, idToCheck))) {
   ...
}
Kevinarpe
quelle