java - programa - jtapi ejemplo
¿Cómo usar la llamada por cobrar en Java 8? (2)
El problema es que Collectors.toList
, como es lógico, devuelve una List<T>
. No es un ArrayList
.
List<Long> ids = remove.stream()
.map(MyObj::getId)
.collect(Collectors.toList());
Programa a la interface
.
De la documentación:
Devuelve un
Collector
que acumula los elementos de entrada en una nuevaList
. No hay garantías sobre el tipo, la mutabilidad, la serialización o la seguridad de subprocesos de laList
devuelta ; Si se requiere más control sobre la Lista devuelta, usetoCollection(Supplier)
.
Énfasis mío: ni siquiera se puede suponer que la List
devuelta sea mutable, y mucho menos que sea de una clase específica. Si quieres un ArrayList
:
ArrayList<Long> ids = remove.stream()
.map(MyObj::getId)
.collect(Collectors.toCollection(ArrayList::new));
Tenga en cuenta también que es habitual usar la import static
con la API de Java 8 Stream
por lo que se agrega:
import static java.util.stream.Collectors.toCollection;
(No me gusta la import static
, no hace más que contaminar el espacio de nombres y agregar confusión. Pero la import static
selectiva, especialmente con las clases de utilidades de Java 8, puede reducir enormemente el código redundante)
Resultaría en:
ArrayList<Long> ids = remove.stream()
.map(MyObj::getId)
.collect(toCollection(ArrayList::new));
Digamos que tenemos este código aburrido que todos tuvimos que usar:
ArrayList<Long> ids = new ArrayList<Long>();
for (MyObj obj : myList){
ids.add(obj.getId());
}
Después de cambiar a Java 8, mi IDE me dice que puedo reemplazar este código con la collect call
, y se genera automáticamente:
ArrayList<Long> ids = myList.stream().map(MyObj::getId).collect(Collectors.toList());
Sin embargo me está dando este error:
collect (java.util.stream.Collector) en Steam no se puede aplicar a: (java.util.stream.Collector, capture, java.util.List>)
Intenté emitir el parámetro pero me está dando A
y R
indefinidos, y el IDE no está dando más sugerencias.
Tengo curiosidad por saber cómo puede usar la collect call
en este escenario, y no pude encontrar ninguna información que pudiera guiarme adecuadamente. ¿Alguien puede arrojar una luz?
Utilizo muchos bloques colectores donde creo una matriz vacía y la lleno utilizando un bucle, así que decidí que necesitaba una clase de utilidad propia para no escribir las mismas líneas de nuevo en el anuncio, aquí está:
public class Collections {
public static <T, O> List<T> collect(Set<O> items, Function<? super O, ? extends T> mapper) {
return items.stream().map(mapper).collect(Collectors.toCollection(ArrayList::new));
}
}
y usalo asi
List<Product> prods = Collections.collect(basket.getOrderItems(), OrderItem::getProduct);
o así
List<Long> prods = Collections.collect(basket.getOrderItems(), (item)->item.getProduct().getId());
Aunque puede parecer mucho más fácil de leer, parece que las transmisiones son un poco más lentas en este tipo de escenarios, mira aquí