Comment vérifier si l'élément existe à l'aide d'une expression lambda?

118

Plus précisément, j'ai TabPane et j'aimerais savoir s'il y a un élément avec un ID spécifique.

Donc, je voudrais faire cela avec l'expression lambda en Java:

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

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

Réponses:

273

Essayez d'utiliser l' anyMatchexpression Lambda. C'est une bien meilleure approche.

 boolean idExists = tabPane.getTabs().stream()
            .anyMatch(t -> t.getId().equals(idToCheck));
Masudul
la source
11
À noter également: si vous souhaitez annuler le chèque, utilisez à la noneMatchplace de anyMatch.
Blacklight
L'appel nécessite le niveau d'API 24
FabioLux
50

Bien que la réponse acceptée soit correcte, j'ajouterai une version plus élégante (à mon avis):

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

Ne négligez pas l'utilisation de Stream # map () qui permet d'aplatir la structure des données avant d'appliquer le Predicate.

jFrenetic
la source
3
quoi de mieux ici? Je ne vois qu'une opération de plus. Désolé, je suis nouveau dans ce truc de lamba.
TecHunter
2
@TecHunter c'est plus explicite. Imaginez que vous lisez ce code la première fois, ou à nouveau après un certain temps. Il y a plusieurs avantages: Premièrement, nous montrons immédiatement que nous ne sommes pas réellement intéressés par l'onglet, mais par une cartographie de celui-ci. Deuxièmement, en utilisant des références de méthode (ce qui n'est possible que parce que nous divisons le lambda initial en deux étapes), nous montrons qu'il n'y a pas de surprises cachées dans le code. Troisièmement, en utilisant des références de méthode, nous ne créons pas un nouveau prédicat, mais nous nous contentons de le réutiliser equals. Bien que, d'accord, l'exemple ici est très simple, mais j'espère que vous comprenez ce que je veux dire.
Malte Hartwig
@MalteHartwig merci! ouais je reçois vos 3 points mais je demandais à propos de l'aplatissement avec map, il fait une autre étape de traitement non? Je vais essayer de comparer les 2 méthodes :)
TecHunter
1
@MalteHartwig testé dans une ArrayList de 10kk avec un objet simple essayant de trouver le dernier élément. donne une différence de 2ms 131ms contre 133ms pour votre. sur un tableau de 1kk, listez le vôtre s'il est plus rapide de 2 ms (55 ms à 53 ms). Nous pouvons donc dire que le vôtre est meilleur :)
TecHunter
2
Les getters @TecHunter sont très bon marché. Préférez toujours la clarté du code à l'économie de 2 millisecondes supplémentaires (même si je doute que les résultats soient exacts, cela peut fluctuer à chaque exécution). En outre, rappelez-vous que les opérations intermédiaires sur les flux (comme map) sont paresseuses par nature. Cela signifie que cette getIdméthode n'est pas appliquée à chaque élément de la collection. Il est évalué paresseusement jusqu'à ce qu'il anyMatchrenvoie vrai .
jFrenetic
3

Les réponses ci-dessus vous obligent à créer un nouvel objet de flux.

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
la source