Nota: esta pregunta es no relacionado con java.util.Optional
.
Cuando se trata de corrientes, que a menudo utilizan la lógica de esta manera:
Stream<FooBar> stream = myInitialStream();
if (needsFilter1) stream = stream.filter(c -> whatever1());
if (needsFilter2) stream = stream.filter(c -> whatever2());
...
return stream.collect(toList());
Lo que estoy tratando de lograr es convertir el código anterior para una sola expresión utilizando el encadenamiento. Me parece más legible y sencillo. Hasta ahora, la única forma que encontró para lograr que era:
return myInitialStream()
.filter(needsFilter1? c->whatever1() : c->true)
.filter(needsFilter2? c->whatever2() : c->true)
.collect(toList());
Sin embargo, esto haría llamadas innecesarias a esas triviales c->true
lamdas, lo que podría producir algún costo rendimiento al aumento de escala.
Así que mi pregunta es: ¿hay una mejor manera de producir expresiones corriente encadenados que incluyen filtrado opcional?
ACTUALIZACIÓN: Tal vez no dejar claro lo suficiente, pero el punto de mi pregunta es encontrar una solución en una sola expresión . Si tengo que utilizar varias instrucciones (para inicializar un predicado, por ejemplo), que también podría utilizar el primer código de bloque de mi pregunta que básicamente hace lo mismo.
Encadenar los predicados de acuerdo con las condiciones usando Predicate::and
el retorno de una nueva predicado.
Predicate<FooBar> predicate = c -> whatever();
if (condition1) { predicate = predicate.and(c -> whatever1()); }
if (condition2) { predicate = predicate.and(c -> whatever2()); }
List<FooBar> dest = list.stream()
.filter(predicate)
.collect(Collectors.toList());
Tras una actualización que solicita una sola expresión. Usted necesita una fuente de condiciones asignadas a los predicados de todos modos. Con la estructura de datos Map<Supplier<Boolean>, Predicate<Integer>>
, donde una clave es una Supplier
de una condición de decidir si un valor ( Predicate<FooBar>
se utiliza).
Reducir las entradas de un mapa a un nuevo Predicate<FooBar>
utilizando el encadenamiento de éstas Predicates
con Predicate::and
, por lo que sus Supplier<Boolean>
rendimientos true
(la condición es válida).
Tener una Map
de las condiciones:
Map<Supplier<Boolean>, Predicate<FooBar>> map = new HashMap<>();
map.put(() -> needsFilter1, c -> whatever1());
map.put(() -> needsFilter2, c -> whatever2());
...
Aquí hay una sola Stream
declaración:
List<Integer> dest = list
.stream()
.filter(map.entrySet() // filter with a predicate ...
.stream()
.filter(e -> e.getKey().get()) // .. where a condition is 'true'
.map(Entry::getValue) // .. get Predicates
.reduce(i -> true, (l, r) -> l.and(r))) // .. reduce them using AND
.collect(Collectors.toList());