java - 如何将 List<Map<Customer, Map<key, BigDecimal>>> 转换为 Map<Customer, Map<key, BigDecimal>>

标签 java java-8 java-stream

我遇到了 java8 流问题。
我有一个

List<Map<Customer, Map<key, BigDecimal>>> 

我想转变成一个

Map<Customer, Map<key, BigDecimal>> 

其中键是月份,BigDecimal 是 BigDecimal 的总和。

我可以通过迭代来做到这一点,但我想使用 java8 流,因为我认为它应该是可能的。
当我迭代时,我使用临时

Map<Customer, List<Map<key, BigDecimal>>>

我通过对每个客户的迭代来减少。

但是要使用流来执行此操作,我必须将元素添加到临时列表中!

有人可以帮忙吗?

最佳答案

在 java 9 中,我们将获得 flatMapping 收集器 ( see here ),这将使此类事情变得更简单。

您可以将 flatMapping 的代码向后移植到您的项目中,当 java 9 发布时,将静态导入替换为官方导入。它看起来像这样:

public static <T, U, A, R>
    Collector<T, ?, R> flatMapping(
        Function<? super T, ? extends Stream<? extends U>> mapper,
        Collector<? super U, A, R> downstream
    ) {
        BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
        return Collector.of(
            downstream.supplier(),
            (r, t) -> {
                try (Stream<? extends U> result = mapper.apply(t)) {
                    if (result != null) {
                        result.sequential()
                        .forEach(u -> downstreamAccumulator.accept(r, u));
                    }
                }
            },
            downstream.combiner(), downstream.finisher(),
            downstream.characteristics().toArray(new Collector.Characteristics[0])
        );
    }

然后你会像这样使用它:

Map<Customer, Map<key, BigDecimal>> result = input.stream()
        .map(Map::entrySet)
        .flatMap(Set::stream)
        .collect(groupingBy(
            e->e.getKey(),
            flatMapping(
                e->e.getValue().entrySet().stream(), 
                toMap(e->e.getKey(), e->e.getValue(), BigDecimal::add)
            )
        ));

如果您不想这样做并且更愿意使用当前标准的收集器,则可以使用 3 参数 toMap,它结合了 map 和 reduce:

Map<Customer, Map<key, BigDecimal>> result = input.stream()
        .map(Map::entrySet)
        .flatMap(Set::stream)
        .collect(toMap(
            e->e.getKey(),
            e->e.getValue(),
            (a,b) -> Stream.of(a,b)   // merge the 2 maps
                    .map(Map::entrySet)
                    .flatMap(Set::stream)
                    .collect(toMap(
                        e->e.getKey(),
                        e->e.getValue(), 
                        BigDecimal::add
                    ))
        ))

关于java - 如何将 List<Map<Customer, Map<key, BigDecimal>>> 转换为 Map<Customer, Map<key, BigDecimal>>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29207999/

相关文章:

java - 使用 java8 stream().map 传递两个参数来调用服务方法

java - 当 Predicate<? 时,强制 Stream::filter 方法在编译时失败传递 super Object> 而不是 Predicate<? super T>

java 使用 FreeMarker 模板写入文本文件

java - java中main的返回类型

Java 8 功能接口(interface)命名约定?

sum - java8流分组聚合

java-8 - Java流操作

java - 如何在java中使用http请求发送文件?

java - 从 fat jar 启动 Dataflow 作业时暂存包时出错

Java 8 方法引用静态 void 方法