首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否可以根据自身计算流中的值?

是否可以根据自身计算流中的值?
EN

Stack Overflow用户
提问于 2022-02-03 07:32:51
回答 4查看 301关注 0票数 3

如果我有一个java流(例如数字),是否有可能计算(通过将数字加到“以前”计算的和中)?

例如(1,2,3,5,7,9,0) -> (1,3,6,11,18,27,27)

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2022-02-03 10:05:08

java流中的数组之和必须使用。

代码语言:javascript
复制
Integer[] arr = {1, 2, 3, 5, 7, 9, 0};
Arrays.parallelPrefix(arr, (x, y) -> x + y);
System.out.println(Arrays.toString(arr));

您必须将用于ArrayList

代码语言:javascript
复制
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);
票数 4
EN

Stack Overflow用户

发布于 2022-02-05 11:47:10

使用流的一个简单解决方案是使用reducing。不过,这个解决方案并不是无状态的。

代码语言:javascript
复制
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]

几点:

在使用流时,应该始终避免

  • 突变。流并不是用来代替命令式代码的,上面的解决方案没有parallelism
  • Streams API的空间,它引入了函数编程(要做什么)范型。它不应该与命令式(如何操作)代码混合。
  • Faeemazaz Bhanej answer中的parallelPrefix解决方案应该是首选的解决方案

票数 1
EN

Stack Overflow用户

发布于 2022-02-03 10:39:43

以下是在this answer上构建概念的证明。它实现了一个具有O(n)时间复杂度的完全无状态解决方案,该解决方案也适用于并行流。

代码语言:javascript
复制
    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);

输出是

代码语言:javascript
复制
[1, 3, 6, 10, 15, 21, 28, 36, 45, 55]

不管是否使用并行流。

请注意,由于在Java中缺少真正的不可变列表,CumSumListStream跳来跳去,这不必要地使这个实现复杂化。另外,acc中的单独跟踪可以通过查看sums中的最后一个元素来代替。为了更清楚起见,我选择不这么做。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70967347

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档