使用流将Map <a,map <b,=“” c =“” >>转换为Map <b,map <a,=“” c =“” >>

时间:2018-11-13 21:07:49

标签: java java-8 java-stream

我有类似地图的结构图:

Map<Center, Map<Product, Value>> given

我想得到

Map<Product, Map<Center, Value>> result

我用过Java流

Map<Product, Map<Center, Value>> result = given.entrySet().stream()
        .flatMap(entry -> entry.getValue()
                 .entrySet().stream()
                 .map(e -> Triple(entry.getKey(), e.getKey(), e.getValue())))
        .collect(Collectors.groupingBy(Triple::getProduct,
                    Collectors.toMap(Triple::getCenter, Triple::getValue)));

其中Triple是简单值类。我的问题是,是否有可能在不使用Triple或例如Table来自番石榴?

2 个答案:

答案 0 :(得分:7)

有些事情在没有流的情况下更容易完成:

Map<Product, Map<Center, Value>> result = new HashMap<>();
given.forEach((c, pv) -> pv.forEach((p, v) ->
        result.computeIfAbsent(p, k -> new HashMap<>()).put(c, v)));

答案 1 :(得分:3)

不幸的是,如果要继续使用流方法,不可避免会创建某种类型的中间对象,即TripleAbstractMap.SimpleEntry或任何其他适用的类型。 / p>

您实质上是在寻找类似C#的匿名类型的东西,即您可以映射到

new { k1 = entry.getKey(), k2 = e.getKey(), k3 = e.getValue()) }

,然后立即访问处于groupingBytoMap阶段的用户。

Java有一些类似的功能,但不完全相同,即您可以:

Map<Product, Map<Center, Value>> result = 
           given.entrySet()
                .stream()
                .flatMap(entry -> entry.getValue()
                        .entrySet().stream()
                        .map(e -> new Object() {
                            Center c = entry.getKey();
                            Product p = e.getKey();
                            Value v = e.getValue();
                        }))
                .collect(Collectors.groupingBy(o -> o.p, Collectors.toMap(o -> o.c, o -> o.v))); 

信用额转到@shmosel。

唯一的好处是您不需要预定义自定义类。