流状态计算:累积总和 [英] Stream stateful computation: cumulative sums

查看:113
本文介绍了流状态计算:累积总和的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个Java IntStream,是否可以将其转换为具有累积总和的IntStream?例如,以[4,2,6,...]开头的流应转换为[4,6,12,...]。



更多一般来说,应该如何实现有状态流操作?感觉这应该是可能的:

  myIntStream.map(new Function< Integer,Integer> {
int sum = 0;
整数适用(整数值){
返还金额+ =价值;
}
);

明显的限制是这仅适用于顺序流。但是,Stream.map明确需要无状态映射函数。我是否正确错过了Stream.statefulMap或Stream.cumulative操作,或者是缺少Java流的点?<​​/ p>

例如比较Haskell,其中scanl1函数解决了正是这个例子:

  scanl1(+)[1 2 3 4] = [1 3 6 10] 


解决方案

您可以使用原子序数执行此操作。例如:

  import java.util.concurrent.atomic.AtomicLong; 
import java.util.stream.IntStream;
import java.util.stream.LongStream;

public class Accumulator {
public static LongStream toCumulativeSumStream(IntStream int){
AtomicLong sum = new AtomicLong(0);
返回ints.sequential()。mapToLong(sum :: addAndGet);
}

public static void main(String [] args){
LongStream sums = Accumulator.toCumulativeSumStream(IntStream.range(1,5));
sums.forEachOrdered(System.out :: println);
}
}

此输出:

  1 
3
6
10

我用Long来存储金额,因为完全有可能两个整数加起来远远超过 Integer.MAX_VALUE 并且很长一段时间有溢出的可能性。


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 to [4, 6, 12, ...].

More generally, how should one go about implementing stateful stream operations? It feels like this should be possible:

myIntStream.map(new Function<Integer, Integer> {
    int sum = 0; 
    Integer apply(Integer value){ 
        return sum += value; 
    }
);

With the obvious restriction that this works only on sequential streams. However, Stream.map explicitely requires a stateless map function. Am I right in missing a Stream.statefulMap or Stream.cumulative operation or is that missing the point of Java streams?

Compare for example to Haskell, where the scanl1 function solves exactly this example:

scanl1 (+) [1 2 3 4] = [1 3 6 10]

解决方案

You can do this with an atomic number. For example:

import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.IntStream;
import java.util.stream.LongStream;

public class Accumulator {
    public static LongStream toCumulativeSumStream(IntStream ints){
        AtomicLong sum = new AtomicLong(0);
        return ints.sequential().mapToLong(sum::addAndGet);
    }

    public static void main(String[] args){
        LongStream sums = Accumulator.toCumulativeSumStream(IntStream.range(1, 5));
        sums.forEachOrdered(System.out::println);
    }
}

This outputs:

1
3
6
10

I've used a Long to store the sums, because it's entirely possible that two ints add up to well over Integer.MAX_VALUE, and a long has less of a chance of overflow.

这篇关于流状态计算:累积总和的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆