Stream stateful computation: cumulative sums

前端 未结 2 952
南旧
南旧 2020-12-01 12:27

Assuming I have a Java IntStream, is it possible to convert it to an IntStream with cumulative sums? For example, a stream starting with [4, 2, 6, ...] should be converted t

2条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-12-01 13:16

    It's possible to do with a collector that then creates a new stream:

    class Accumulator {
        public static void accept(List list, Integer value) {
            list.add(value + (list.isEmpty() ? 0 : list.get(list.size() - 1)));
        }
    
        public static List combine(List list1, List list2) {
            int total = list1.get(list1.size() - 1);
            list2.stream().map(n -> n + total).forEach(list1::add);
            return list1;
        }
    }
    

    This is used as:

    myIntStream.parallel()
        .collect(ArrayList::new, Accumulator::accept, Accumulator::combine)
        .stream();
    

    Hopefully you can see that the important attribute of this collector is that even if the stream is parallel as the Accumulator instances are combined it adjusts the totals.

    This is obviously not as efficient as a map operation because it collects the whole stream and then produces a new stream. But that's not just an implementation detail: it's a necessary function of the fact that streams are intended to be potentially concurrently processed.

    I have tested it with IntStream.range(0, 10000).parallel() and it functions correctly.

提交回复
热议问题