2

使用 java 8 我想从列表中创建一个新集合并在此过程中累积一个总和。

源列表由如下所示的对象组成:

class Event {
  String description;
  double sum;
}

使用这样的示例列表:

{ { "desc1", 10.0 }, {"desc2", 14.0 }, {"desc3", 5.0 } }

结果列表应如下所示

  • desc1, 10.0, 10.0
  • 描述2、14.0、24.0
  • 描述3、5.0、29.0

我知道如何求和以获得最终总和,在本例中为 29.0,但我想创建结果列表并同时累积总和。

我怎么能用Java8做到这一点?

4

2 回答 2

4

您可以通过实现自己的收集器来执行映射和求和来做到这一点。您的流式传输代码如下所示:

List<SummedEvent> summedEvents = events.stream().collect(EventConsumer::new, EventConsumer::accept, EventConsumer::combine).summedEvents();
summedEvents.forEach((se) -> System.out.println(String.format("%s, %2f, %2f", se.description, se.sum, se.runningTotal)));

为此,我假设了一个新类SummedEvent,它也包含运行总数。然后您的收集器类将实现如下:

class EventConsumer {
    private List<SummedEvent> summedEvents = new ArrayList<>();
    private double runningTotal = 0;

    public void accept(Event event) {
        runningTotal += event.sum;
        summedEvents.add(new SummedEvent(event.description, event.sum, runningTotal));
    }
    public void combine(EventConsumer other) {
        this.summedEvents.addAll(other.summedEvents);
        this.runningTotal += other.runningTotal;
    }

    public List<SummedEvent> summedEvents() {
        return summedEvents;
    }
}
于 2015-03-14T12:47:50.913 回答
3

如果您将按顺序运行您的管道,您可以将这个小技巧与peek.

double[] acc = {0};
List<CustomEvent> list = originalList.stream()
                                     .peek(e -> acc[0] += e.sum)
                                     .map(e -> new CustomEvent(e, acc[0]))
                                     .collect(toList());

请注意,如果流并行运行,您将得到错误的结果。

但是我不确定管道是否可以一次并行运行,但假设底层列表可以快速访问索引处的元素,i您可以这样做:

double[] acc = originalList.stream().mapToDouble(e -> e.sum).toArray();
Arrays.parallelPrefix(acc, Double::sum);

List<CustomEvent> lx = IntStream.range(0, originalList.size())
                                .parallel()
                                .mapToObj(i -> new CustomEvent(originalList.get(i), acc[i]))
                                .collect(toList());

parallelPrefix将应用您正在寻找的总和的减少。然后,您只需流式传输索引并将每个事件映射到其相应的累积总和。

于 2015-03-14T13:25:52.127 回答