首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java 8-积累和创建新的集合

Java 8-积累和创建新的集合
EN

Stack Overflow用户
提问于 2015-03-14 12:09:38
回答 2查看 3.1K关注 0票数 2

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

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

代码语言:javascript
复制
class Event {
  String description;
  double sum;
}

下面是一个示例列表:

代码语言:javascript
复制
{ { "desc1", 10.0 }, {"desc2", 14.0 }, {"desc3", 5.0 } }

结果列表应该如下所示

  • desc1,10.0,10.0
  • desc2,14.0,24.0
  • desc3,5.0,29.0

我知道如何总结得到最后的和,在这个例子中是29.0,但是我想要创建结果列表,同时在这个过程中积累和。

我怎样才能用Java8做到这一点呢?

EN

回答 2

Stack Overflow用户

发布于 2015-03-14 12:47:50

您可以通过实现自己的收集器来执行映射和汇总。您的流代码将如下所示:

代码语言:javascript
复制
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,它也保存正在运行的总计。然后,您的收集器类将实现如下所示:

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

Stack Overflow用户

发布于 2015-03-14 13:25:52

如果您将按顺序运行管道,则可以在peek中使用这个小黑客。

代码语言:javascript
复制
double[] acc = {0};
List<CustomEvent> list = originalList.stream()
                                     .peek(e -> acc[0] += e.sum)
                                     .map(e -> new CustomEvent(e, acc[0]))
                                     .collect(toList());

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

但是,我不确定管道是否可以在一次传递中并行运行,但假设基础列表能够快速访问索引i上的元素,您可以这样做:

代码语言:javascript
复制
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将应用您正在寻找的金额减少。然后,您只需流索引,并将每个事件映射到相应的累积和。

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

https://stackoverflow.com/questions/29048739

复制
相关文章

相似问题

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