【问题标题】:Calculating List of cumulative sums from List of integers with Java streams从具有 Java 流的整数列表中计算累积和列表
【发布时间】:2020-08-21 16:21:12
【问题描述】:

我有以下清单:

 INPUT :: 4 5 8 -11 9 5 -7 4 6 -6 -8 -11 80 -32 -56 -15 5 -49 

 OUTPUT :: 4 9 17 6 15 20 13 17 23 17 9 -2 78 46 -10 -25 -20 -69

我需要计算累计和 - 列表含义

T(n) = T(n) + T(n-1) for n >0; 
and
T(0) = T(0)

我想用 Java 流 API 来计算它,以便我可以用 Spark 实现它来进行大数据计算。我在 Java Streams 中很天真我尝试了几种表达方式,但它们都不起作用 等效的结构化代码应该是这样的:

int[] numbers = {4, 5, 8, -11, 9, 5, -7, 4, 6,-6, -8, -11, 80, -32, -56, -15, 5, -49};
int temp = 0;

for (int i = 0 ; i < numbers.length ; i++) {
   temp = temp + numbers[i];
   numbers[i] = temp;
}

【问题讨论】:

  • Stream API 在这里没有任何好处。
  • spark有什么关系?
  • @Lamanus 我可以将此解决方案与 Spark 中 JavaRDD 的一些数据类型更改一起使用
  • @Nikolas,我对 Stream API 完全陌生,你能帮我理解为什么 Stream 不能工作吗?如何以功能的方式实现这个逻辑?
  • @NilKulkarni Streams 将起作用。但是没有额外的好处,实际上增加了额外的开销。

标签: java lambda java-8 java-stream


【解决方案1】:

试试这个。

int[] a = {4, 5, 8, -11, 9, 5, -7, 4, 6, -6, -8, -11, 80, -32, -56, -15, 5, -49};
Arrays.parallelPrefix(a, (x, y) -> x + y);
System.out.println(Arrays.toString(a));

输出:

[4, 9, 17, 6, 15, 20, 13, 17, 23, 17, 9, -2, 78, 46, -10, -25, -20, -69]

【讨论】:

  • 谢谢,虽然不能投票,我没有足够的声誉
  • 当然是流的首选方法。但是 OP 确实指定了一个流解决方案。
【解决方案2】:

这里有两种方法。

第一个效率非常低,因为它基本上使用嵌套循环来累积值。第一个 IntStream 指定值的范围,嵌套的 IntStream 创建一个变量范围并将从 0 到该范围末尾的值相加。

int[] result1 = IntStream.range(0, vals.length).map(
        i -> IntStream.rangeClosed(0, i).map(k->vals[k]).reduce(0, (a, b) -> a + b))
        .toArray();

这个更符合一种更传统的方法。流式传输一个 0 数组,然后使用它来累积值的运行总和。

int[] result2 = Stream.of(new int[] { 0 })
        .flatMapToInt(k -> IntStream.of(vals).map(v -> {
            k[0] += v;
            return k[0];
        })).toArray();

System.out.println(Arrays.toString(result1));
System.out.println(Arrays.toString(result2));

都打印

[4, 9, 17, 6, 15, 20, 13, 17, 23, 17, 9, -2, 78, 46, -10, -25, -20, -69]
[4, 9, 17, 6, 15, 20, 13, 17, 23, 17, 9, -2, 78, 46, -10, -25, -20, -69]

但你根本无法做得比这更好。

for (int i = 1; i < vals.length; i++) {
      vals[i] += vals[i-1];
}

底线是坚持你所拥有的。

【讨论】:

  • 谢谢。这让我大开眼界,Streams 可能不会每次都带来好处..
【解决方案3】:

您可以尝试使用自定义收集器。

public static void main(String[] args) {
       List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
       List<Integer> cumulatives = integers.stream().collect(CumulativeAdd.collector());
}
     private static final class CumulativeAdd {

       List<Integer> retArray= new ArrayList<>();
       int sum = 0; 

       public void accept(Integer num) {
           sum +=num;
           retArray.add(sum);
       }

       public CumulativeAdd combine(CumulativeAdd other) {
           throw new UnsupportedOperationException("Parallel Stream not supported");
       }

       public List<Integer> finish() {
           return retArray;
       }

       public static Collector<Integer, ?, List<Integer>> collector() {
           return Collector.of(CumulativeAdd::new, CumulativeAdd::accept, CumulativeAdd::combine, CumulativeAdd::finish);
       }

   }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-05
    • 2016-07-23
    • 2020-10-20
    • 2020-09-26
    • 2018-07-26
    • 1970-01-01
    • 1970-01-01
    • 2020-07-18
    相关资源
    最近更新 更多