【问题标题】:Java8: Reduce list of elements like sql group byJava8:减少元素列表,如 sql group by
【发布时间】:2015-03-06 15:36:25
【问题描述】:

在 List 上的 stream().filter().map() 之后,我有一个 List<List<Object>> 类型的数据结构,如下所示:

[["1","a",20],
 ["1","b",10],
 ["2","a",10],
 ["2","b",30]]

我想要的是按内部列表的第一个元素的值进行分组,将中间元素排除在外,最后将每个“组”的最后一个元素相加。

[["1", 30],
 ["2", 40]]

对不起,如果这对你们中的某些人来说是显而易见的,但我还没有找到任何例子来说明如何实现这一点。我认为它可以通过 Stream.reduce(U identity, BiFunction accumulator, BinaryOperator combiner) 来完成,但到目前为止我还没有成功。如果有人可以为此提供一些示例代码,我相信它也会受到许多其他人的赞赏。

【问题讨论】:

  • 当我认为这是正确的使用方法时,我是否误解了“减少”的概念?

标签: functional-programming java-8 reduce java-stream


【解决方案1】:

以下代码可能会有所帮助:

List<List<Object>> originalList = Arrays.asList(
        Arrays.asList("1", "a", 20),
        Arrays.asList("1", "b", 10),
        Arrays.asList("2", "a", 10),
        Arrays.asList("2", "b", 30)
);

final Map<Object, Integer> collectedMap =
        originalList.stream()
                .collect(Collectors.groupingBy(
                        e -> e.get(0),
                        Collectors.summingInt(e -> (Integer) e.get(2))));

System.out.println(collectedMap);

输出是:

{1=30, 2=40}

基本上,代码所做的是通过子列表中的第一个值 (get(0)) 到 group。然后它使用summingInt 对整数求和。但是,它将整个内容分组到 Map 中 - 如果需要其他一些集合,则必须稍微更改流。

例如将整个东西收集为List

final List<List<Object>> collectedList =
    collectedMap.entrySet()
             .stream()
             .map(e -> Arrays.asList(e.getKey(), e.getValue()))
             .collect(Collectors.toList());

System.out.println(collectedList);

然后,输出将是:

[[1, 30], [2, 40]]

【讨论】:

  • 谢谢。我被锁定在 .reduce() 模式中,并且不知道收集器的可能性!但是,我确实需要最终结果是一个列表,但如果需要,我当然可以在单独的操作中做到这一点。
  • @aweibell:我还添加了一个示例,说明如何将其收集为List
  • 谢谢。我在生成的地图上使用 .forEach 完成了它。 :)
  • 可能不如 collect 变体干净,因为我手动实例化并填充了列表。
  • 你也可以像这样使用Collectors.toMap()originalList.stream().collect(Collectors.toMap(e -&gt; e.get(0), e -&gt; (Integer) e.get(2), (a, b) -&gt; a + b))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-21
  • 2014-08-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多