Java 8: omitir el tedioso método de recopilación
java-8 java-stream (10)
Con cyclops-react tienes varias opciones.
Podemos hacer uso de las colecciones extendidas de Lazy
CollectionX<String> collection = ListX.of("hello","world");
CollectionX<String> filtered = collection.filter(p->p.isCorrect());
Hay soporte para colecciones extendidas mutables, inmutables y persistentes. Las operaciones funcionales en las colecciones son perezosas (es decir, se comportan como secuencias reproducibles) y se materializan solo en el primer acceso.
Podemos hacer uso de un poderoso tipo de Stream extendido
ReactiveSeq.fromIterable(collection)
.filter(p->p.isCorrect())
.toList();
[Divulgación Soy el desarrollador principal de cyclops-react]
Java 8 stream api es una característica muy agradable y me gusta mucho.
Una cosa que me pone de los nervios es que el 90% del tiempo quiero tener entrada como colección y salida como colecciones.
La consecuencia es que tengo que llamar al método
stream()
y
collect()
todo el tiempo:
collection.stream().filter(p->p.isCorrect()).collect(Collectors.toList());
¿Hay alguna API Java que me permita omitir la transmisión y operar directamente en colecciones (como
linq
en c #?):
collection.filter(p->p.isCorrect)
Las transmisiones tenían una arquitectura bien definida, sobre la cual puedes leer mucho . Es posible que desee leer sobre eso antes de comenzar este camino.
Pero, ¿por qué no implementar una colección que implemente una interfaz de transmisión similar que envuelva ese código por usted?
public class StreamableCollection implements Collection, Stream {
...
}
Entonces podría hacer algunas suposiciones difíciles para su caso de uso. Todavía podría abrir una transmisión desde la interfaz de colecciones, pero también podría saltar directamente hacia adentro y luego en el interior de ese control, supongo.
streamableCollection cs = new streamableCollection();
cs.filter();
cs.stream();
Su IDE lo llevará a implementar todo ... simplemente devuelva todo a las implementaciones predeterminadas.
Puede probar esto, de la biblioteca de guayaba. Parece un poco menos abarrotado que el enfoque Stream.
ImmutableList.copyOf(Iterables.filter(collection, MyClass::isCorrect));
Consulte Google Collections (Bibliotecas de guayaba): ImmutableSet / List / Map and Filtering para una discusión sobre la técnica.
Puede que te guste usar StreamEx
StreamEx.of(collection).filter(PClass::isCorrect).toList();
Esto tiene las ventajas de ser un poco más breve mientras se mantiene la inmutabilidad.
Sí, hay varias bibliotecas que abordan la verbosidad de flujo de Java 8. Una lista incompleta:
Mi preferencia va con jOOL. Lo he estado usando en mis últimos proyectos. Los otros que conozco pero que realmente no usé, así que no puedo darte una impresión.
Su ejemplo con jOOL sería:
Seq.seq(collection).filter(p->p.isCorrect()).toList();
Sí, usando
Collection#removeIf(Predicate)
:
Elimina todos los elementos de esta colección que satisfacen el predicado dado.
Tenga en cuenta que cambiará la colección dada, no devolverá una nueva. Pero puede crear una copia de la colección y modificarla. También tenga en cuenta que el predicado necesita ser negado para actuar como un filtro:
public static <E> Collection<E> getFilteredCollection(Collection<E> unfiltered,
Predicate<? super E> filter) {
List<E> copyList = new ArrayList<>(unfiltered);
// removeIf takes the negation of filter
copyList.removeIf(e -> { return !filter.test(e);});
return copyList;
}
Pero como sugiere @Holger en los comentarios, si elige definir este método de utilidad en su código y usarlo en todas partes donde necesite obtener una colección filtrada, simplemente delegue la llamada al método de
collect
en esa utilidad.
Su código de llamada será más conciso.
public static <E> Collection<E> getFilteredCollection(Collection<E> unfiltered,
Predicate<? super E> filter) {
return unfiltered.stream()
.filter(filter)
.collect(Collectors.toList());
}
Si desea operar en colecciones, ¡ Guava''s FluentIterable es un camino a seguir!
Ejemplo (obtener id de 10 primeros clientes vip):
FluentIterable
.from(customers)
.filter(customer -> customer.isVIP())
.transform(Client::getId)
.limit(10);
Si está abierto a usar una biblioteca de terceros, puede usar Eclipse Collections, que tiene API enriquecidas directamente disponibles en colecciones. Su ejemplo se puede escribir de la siguiente manera con Eclipse Collections.
collection.select(p->p.isCorrect)
collection.select(MyClass::isCorrect)
Nota: Soy un committer para Eclipse Collections.
Si necesita una vista filtrada sin modificar la colección original, considere Guava''s
Collections2.filter()
.
También creo que Stream API es bueno, pero detallado para operaciones cortas. He usado estos métodos de utilidad en algunos proyectos:
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Functions {
public static <T,V> List<V> map(final List<T> in, final Function<T, V> function) {
return in == null ? null : map(in.stream(), function);
}
public static <T,V> List<V> map(final Stream<T> in, final Function<T, V> function) {
return in == null ? null : in
.map(function)
.collect(Collectors.toList());
}
public static <T> List<T> filter(final List<T> in, final Predicate<T> predicate) {
return in == null ? null : filter(in.stream(), predicate);
}
public static <T> List<T> filter(final Stream<T> in, final Predicate<T> predicate) {
return in == null ? null : in
.filter(predicate)
.collect(Collectors.toList());
}
}
Esto me permite hacer, por ejemplo
List<String> wrapped = Functions.map(myList, each -> "[" + each + "]");
Normalmente también importo estática el método.