una sumar streams recorrer procesamiento parte lista libreria examples elementos ejemplos datos con collection java collections java-8 sum java-stream

sumar - Java 8 Stream agrega elementos a la lista y suma



stream java examples (4)

Lo que quiere aquí es recopilar sus elementos dentro de 2 coleccionistas: el primero se reuniría en una lista y el segundo sumaría el precio.

Como no hay tales recopiladores en Stream API, podemos construir fácilmente los nuestros. ResultHolder una clase ResultHolder que contendrá el resultado de la canalización de Stream: esta es la lista de decimales y la suma.

class ResultHolder { List<BigDecimal> list = new ArrayList<>(); BigDecimal sum = BigDecimal.ZERO; }

Finalmente, podemos usarlo con:

ResultHolder resultHolder = listOfPricedObjects.stream() .map(PricedObject::getPrice) .collect( ResultHolder::new, (r, p) -> { r.list.add(p); r.sum = r.sum.add(p); }, (r1, r2) -> { r1.list.addAll(r2.list); r1.sum = r1.sum.add(r2.sum); } ); System.out.println(resultHolder.list); System.out.println(resultHolder.sum);

Esto funcionará en una tubería paralela y mantendrá el orden inicial de la lista, a diferencia de las otras respuestas.

Creo que puedo hacer lo siguiente usando una operación de flujo en listOfPricedObjects:

List<BigDecimal> myList = new ArrayList(); myList = listOfPricedObjects.stream().map(PricedObject::getPrice).collect(Collectors.toList()); BigDecimal sum = listOfPricedObjects.stream().map(PricedObject::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add)

¿Cómo puedo completar myList con los precios y calcular la suma de los precios usando stream una vez? Gracias

UPD: Como resultado necesito myList lleno de precios y variable de suma con suma. Pero no con usar stream () dos veces para eso.


Podría hacer un mapeo de identidad agregar el valor de paso a la lista

BigDecimal sum = listOfPricedObjects.stream() .map(o -> { myList.add(o); return o;}) .map(PricedObject::getPrice) .reduce(BigDecimal.ZERO, BigDecimal::add)

Pero iría por la solución de Sleiman Jneidi usando peek (), es más elegante


Si bien podría ser razonable suponer casos de uso en los que una secuencia arbitraria como listOfPricedObjects no puede recrearse desde el origen y, por lo tanto, listOfPricedObjects solo una vez, puede asumir con seguridad que atravesar la lista producida mediante Collectors.toList() puede atravesarse de manera eficiente:

List<BigDecimal> myList = listOfPricedObjects.stream() .map(PricedObject::getPrice).collect(Collectors.toList()); BigDecimal sum = myList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO);

No hay duplicación de código aquí y cualquier intento de realizar estas dos operaciones no relacionadas en un cruce de flujo hará que el código sea más complicado sin ningún beneficio.


Puede usar peek y agregar a una nueva list mientras aplica la reducción

List<BigDecimal> newList = new ArrayList<>(); BigDecimal sum = list.stream() .map(PricedObject::getPrice) .peek(newList::add) .reduce(BigDecimal.ZERO, BigDecimal::add);

Mire la respuesta de Tunaki si está interesado en usar un parallelStream con una colección no simultánea que tenga sentido, ya que sum es una tarea embarazosamente paralela.