¿Cómo verificar si el elemento existe usando una expresión lambda?

118

Específicamente, tengo TabPane y me gustaría saber si hay un elemento con una ID específica en él.

Entonces, me gustaría hacer esto con la expresión lambda en Java:

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

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

Respuestas:

273

Intente utilizar anyMatchLambda Expression. Es un enfoque mucho mejor.

 boolean idExists = tabPane.getTabs().stream()
            .anyMatch(t -> t.getId().equals(idToCheck));
Masudul
fuente
11
También vale la pena señalar: si desea negar el cheque, utilice en noneMatchlugar de anyMatch.
Blacklight
La llamada requiere nivel de API 24
FabioLux
50

Si bien la respuesta aceptada es correcta, agregaré una versión más elegante (en mi opinión):

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

No descuide el uso de Stream # map () que permite aplanar la estructura de datos antes de aplicar el Predicate.

jFrenético
fuente
3
que es mejor aqui Solo veo una operación más. Lo siento, soy nuevo en esto de lamba.
TecHunter
2
@TecHunter es más explícito. Imagina que lees este código por primera vez o de nuevo después de un tiempo. Hay varias ventajas: Primero, mostramos inmediatamente que no estamos realmente interesados ​​en la pestaña, sino en un mapeo de la misma. En segundo lugar, al usar referencias de métodos (que solo es posible porque dividimos la lambda inicial en dos pasos) mostramos que no hay sorpresas ocultas en el código. En tercer lugar, al utilizar referencias de métodos, no creamos un nuevo predicado, sino que simplemente lo reutilizamos equals. Aunque, por supuesto, el ejemplo aquí es muy simple, pero espero que entiendas lo que quiero decir.
Malte Hartwig
@MalteHartwig gracias! Sí, obtuve sus 3 puntos, pero estaba preguntando sobre el aplanamiento con map, ¿hace otro paso de procesamiento, no? Intentaré comparar los 2 métodos :)
TecHunter
1
@MalteHartwig probado en un ArrayList de 10kk con un objeto simple tratando de encontrar el último elemento. da una diferencia de 2ms 131ms contra 133ms para su. en una matriz de 1kk, enumere el suyo si es más rápido en 2 ms (55 ms a 53 ms). Entonces podemos decir que el tuyo es mejor :)
TecHunter
2
Los captadores de @TecHunter son súper baratos. Prefiera siempre la claridad del código en lugar de guardar 2 milisegundos adicionales (aunque dudo que los resultados sean precisos, puede fluctuar en cada ejecución). Además, recuerde que las operaciones intermedias en streams (como map) son perezosas por naturaleza. Eso significa que el getIdmétodo no se aplica a cada elemento de la colección. Se evalúa perezosamente hasta que anyMatchdevuelve verdadero .
jFrenetic
3

Las respuestas anteriores requieren que coloques mal un nuevo objeto de flujo.

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
fuente