Si tengo un flujo de java de, por ejemplo, números, ¿es posible calcular, por ejemplo, las sumas hasta ese número (agregando el número a la suma calculada "anteriormente")?
por ejemplo (1, 2, 3, 5, 7, 9, 0) --> (1, 3, 6, 11, 18, 27, 27)
Una solución simple usando Streams es usar reducing . Sin embargo, esta solución no es apátrida .
var inputList = List.of(1, 2, 3, 5, 7, 9, 0); var result = new ArrayList<>(); var unused = inputList.stream().collect(reducing(0, (a, b) -> { result.add(a + b); return a + b; })); System.out.println(result); // [1, 3, 6, 11, 18, 27, 27]Algunos puntos:
parallelPrefix en la respuesta de Faeemazaz Bhanej debería ser la solución preferidasí, puede usar un recopilador personalizado para hacer eso. Aunque la parte del "stream" no tendría nada que ver.
Se vería como list.stream().collect( new CustomSequentialCollector() )
Tienes que usarparaleloPrefijo para la suma de la matriz en el flujo de Java.
Integer[] arr = {1, 2, 3, 5, 7, 9, 0}; Arrays.parallelPrefix(arr, (x, y) -> x + y); System.out.println(Arrays.toString(arr));Tienes que usar AtomicInteger para ArrayList
List<Integer> list = new ArrayList<>(); list.addAll(Arrays.asList(1, 2, 3, 5, 7, 9, 0)); AtomicInteger ai = new AtomicInteger(); List<Integer> sumOfList = list.stream() .map(ai::addAndGet) .collect(Collectors.toList()); System.out.println(sumOfList);Aquí hay una prueba de concepto basada en esta respuesta . Implementa una solución totalmente sin estado con complejidad de tiempo O(n) que también funciona con flujos paralelos.
record CumSum(Integer acc, List<Integer> sums) { public CumSum() { this(0, List.of()); } public CumSum collect(Integer n) { return new CumSum(acc + n, concat(sums, Stream.of(acc + n))); } public CumSum combine(CumSum cumSum) { return new CumSum(acc + cumSum.acc, concat(sums, cumSum.sums.stream().map(n -> acc + n))); } private static List<Integer> concat(List<Integer> sums, Stream<Integer> acc) { return Stream.concat(sums.stream(), acc).toList(); } } var list1 = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); var list2 = list1.stream().parallel() .reduce(new CumSum(), CumSum::collect, CumSum::combine) .sums; System.out.println(list2);la salida es
[1, 3, 6, 10, 15, 21, 28, 36, 45, 55]independientemente de usar una secuencia paralela o no.
Tenga en cuenta que, debido a la falta de una verdadera Lista inmutable en Java, CumSum salta hacia adelante y hacia atrás de List y Stream , lo que complica esta implementación innecesariamente. Además, el seguimiento separado en acc podría reemplazarse simplemente mirando el último elemento en sums . Para mayor claridad, elegí no hacer eso.