Como verificar se o elemento existe usando uma expressão lambda?

118

Especificamente, eu tenho TabPane e gostaria de saber se há um elemento com ID específico nele.

Então, eu gostaria de fazer isso com a expressão lambda em Java:

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

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

Respostas:

273

Tente usar a anyMatchexpressão Lambda. É uma abordagem muito melhor.

 boolean idExists = tabPane.getTabs().stream()
            .anyMatch(t -> t.getId().equals(idToCheck));
Masudul
fonte
11
Também vale a pena notar: se você quiser negar o cheque, use em noneMatchvez de anyMatch.
Blacklight
A chamada requer API de nível 24
FabioLux
50

Embora a resposta aceita seja correta, adicionarei uma versão mais elegante (na minha opinião):

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

Não negligencie o uso de Stream # map (), que permite nivelar a estrutura de dados antes de aplicar o Predicate.

jFrenetic
fonte
3
o que é melhor aqui? Só vejo mais uma operação. Desculpe, eu sou novo nessa coisa de lamba.
TecHunter
2
@TecHunter é mais explícito. Imagine que você leu este código pela primeira vez ou novamente depois de um tempo. Existem várias vantagens: Primeiro, mostramos imediatamente que não estamos realmente interessados ​​na guia, mas sim em algum mapeamento dela. Em segundo lugar, usando referências de método (o que só é possível porque dividimos o lambda inicial em duas etapas), mostramos que não há surpresas ocultas no código. Terceiro, usando referências de método, não criamos um novo Predicado, mas apenas o reutilizamos equals. Embora, claro, o exemplo aqui seja muito simples, mas espero que você entenda o que quero dizer.
Malte Hartwig
@MalteHartwig obrigado! sim eu recebo seus 3 pontos, mas estava perguntando sobre o nivelamento com map, ele faz outra etapa de processamento, não? Vou tentar comparar os 2 métodos :)
TecHunter
1
@MalteHartwig testado em um ArrayList de 10kk com um objeto simples tentando encontrar o último elemento. dá uma diferença de 2ms de 131ms contra 133ms do seu. em uma lista de matriz de 1kk a sua se for mais rápida em 2ms (55ms a 53ms). Portanto, podemos dizer que o seu é melhor :)
TecHunter
2
Os getters @TecHunter são superbaratos. Sempre prefira clareza de código em vez de economizar 2 milissegundos extras (embora, eu duvide que os resultados sejam precisos, ele pode flutuar a cada execução). Além disso, lembre-se de que as operações intermediárias em fluxos (como map) são preguiçosas por natureza. Isso significa que o getIdmétodo não se aplica a cada elemento da coleção. Ele é avaliado vagarosamente até anyMatchretornar verdadeiro .
jFrenetic
3

As respostas acima exigem que você marque um novo objeto de fluxo.

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
fonte