español - lambda expressions java 8
Java 8 Lambdas-Bitwise Y Operaciones (3)
¿No debería ser algo como esto?
boolean areAllSuccessful = entries.stream()
.map(entry -> entry.isSuccessful())
.reduce(Boolean.TRUE, Boolean::logicalAnd);
Actualmente estoy abordando el tema de la transformación de bucles que utilizan operaciones bitwise utilizando Lambdas en Java 8.
Dado un conjunto de entradas complejas, se requiere que el bucle atraviese TODAS las entradas y llame un método dado (el método devuelve un valor booleano). Después, devuelve el resultado.
En otras palabras, necesito llamar al método en todas las entradas y almacenar el resultado. La razón detrás de esto es que cada entrada realiza de forma independiente una operación compleja y debe realizarse. El resultado final es una combinación de resultados.
Fragmento de código:
boolean areAllSuccessful = true;
for (SomeEntry entry : entries) {
areAllSuccessful = areAllSuccessful & entry.doComplexAction(); // keep calling the method on other entries regardless of the result.
}
return areAllSuccessful;
El problema es que las funciones Lambda en Java 8 generalmente realizan operaciones de cortocircuito (una vez que se ha detectado la entrada falsa, se interrumpe el "bucle" y se devuelve el resultado falso).
Mi mejor solución hasta ahora fue usar la combinación mapa / filtro / conteo:
return entries
.stream()
.map(entry -> entry.doComplexAction())
.filter(result -> result == false)
.count() > 0
¿Hay una forma más inteligente / limpia de hacer esto?
¡Gracias!
La forma más limpia y eficiente es usar una referencia de método con allMatch()
return entries.stream().allMatch(SomeEntry::isSuccessful);
Si tiene miles de elementos, considere usar parallelStream()
lugar.
Esto no procesa todos los elementos (se devuelve en el primer false
), por lo que si su método isSuccessful()
tiene efectos secundarios, es un mal nombre y debe cambiar su nombre o refactorizar el código para realizar los efectos secundarios en un process()
(o un método similar) y tienen isSuccessful()
devuelve el resultado, lanzando una IllegalStateException
si el process()
no ha sido llamado primero.
Si no se refactoriza, algún desarrollador (incluido usted) llamará a isSuccessful()
sin darse cuenta de que "hace cosas", lo que podría ser malo.
Realmente no necesitas map()
si vas a usar count()
:
return !(entries
.stream()
.filter(entry -> !entry.isSuccessful())
.count() > 0);
Si el método isSuccessful()
no tuvo efectos secundarios, y todo lo que necesitaba saber era si todas las entradas fueron exitosas, podría haber usado allMatch()
:
return entries
.stream()
.allMatch(entry -> entry.isSuccessful());
De hecho, esta es una operación de cortocircuito que devolverá el valor false
tan pronto como encuentre una entrada donde isSuccessful()
sea false
, y no consumirá todo el flujo a menos que sea necesario. Pero usted ya comentó que el isSuccesful()
realmente isSuccesful()
significa "hacer algunas acciones complejas y luego decirme si tuvieron éxito", por lo que no se aplica.