Java8:减少像sql group by这样的元素列表

时间:2015-01-08 13:41:49

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

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

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

我想要的是按内部列表的第一个元素的值进行分组,保留中间元素,最后将每个&#34; group&#34;的最后元素相加。

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

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

1 个答案:

答案 0 :(得分:5)

以下代码可能有所帮助:

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}

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

E.g。将整个事物收集为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]]