Java 结果是按列表分组

Java 结果是按列表分组,java,java-8,java-stream,collectors,groupingby,Java,Java 8,Java Stream,Collectors,Groupingby,我们有以下几点: public List<Balance> mapToBalancesWithSumAmounts(List<MonthlyBalancedBooking> entries) { return entries .stream() .collect( groupingBy( MonthlyBalancedBooking::getValidFor, summingDoubl

我们有以下几点:

public List<Balance> mapToBalancesWithSumAmounts(List<MonthlyBalancedBooking> entries) {
    return entries
      .stream()
      .collect(
        groupingBy(
          MonthlyBalancedBooking::getValidFor,
          summingDouble(MonthlyBalancedBooking::getAmount)
        )
      )
      .entrySet()
      .stream()
      .map(localDateDoubleEntry -> new Balance(localDateDoubleEntry.getValue(), localDateDoubleEntry.getKey()))
      .collect(toList());
  }

是否有可能避免代码中的第二个流路径,因此在本例中,groupingBy的结果应该是一个列表。我们需要将map函数传递给collect或groupby,这在Java 8中是可能的吗?

简单的方法是使用带有merge函数的toMap collector,如下所示:

List<Balance> balances = new ArrayList<>(entries.stream()
       .collect(toMap(MonthlyBalancedBooking::getValidFor, m -> new Balance(m.getAmount(),
                                              m.getValidFor()),Balance::merge)).values());

这是不可能的,因为只有在迭代MonthlyBalancedBooking列表的所有条目后,才能计算映射到Balance对象时所查找的值

new Balance(localDateDoubleEntry.getValue(), localDateDoubleEntry.getKey())
但是,在单个终端操作中移动流的另一种方法是使用collectingAndThen as:


你的java版本是什么?java 8:但是对于有同样问题的人来说,更现代的java版本的解决方案也可以发布。@ChristianWiedehöft这甚至不可能,因为风格也是必须的。除非平衡对象是可变的,并且可以以某种方式围绕唯一关键点移动。我建议两方面都试试。移动到单个流调用的原因是什么?您可以创建自己的收集器,在第一次过程中进行合并。我们正在寻找一种无需打开第二个流的解决方案。如果可能的话,;这只会移动第二条流的创建,但OP希望完全避免第二条流。@ChristianWiedehöft这是不可能的。请看更新。我确实对此进行了思考,因此发表了评论。这里的问题是为地图选择的关键,然后决定如何合并。使用中间映射操作创建的对象可能有缺陷。非常优雅的解决方案。我唯一要改变的是将merge方法移出POJO。为此目的使用静态实用方法是更灵活的方法。您可能无法访问Balance类的源代码。您还必须添加Balance::getKey,它在问题代码中不存在。或者您放弃映射操作,更接近问题的代码:entries.stream.CollectToManthlyBalancedBooking::getValidFor,m->new Balancem.getAmount,m.getValidFor,Balance::merge
new Balance(localDateDoubleEntry.getValue(), localDateDoubleEntry.getKey())
public List<Balance> mapToBalancesWithSumAmounts(List<MonthlyBalancedBooking> entries) {
    return entries.stream()
            .collect(Collectors.collectingAndThen(
                    Collectors.groupingBy(MonthlyBalancedBooking::getValidFor,
                            Collectors.summingDouble(MonthlyBalancedBooking::getAmount)),
                    map -> map.entrySet().stream()
                            .map(entry -> new Balance(entry.getValue(), entry.getKey()))))
            .collect(Collectors.toList());
}