Преобразовать карту <A, карту <B, C >> в карту <B, карту <A, C >>, используя потоки - PullRequest
0 голосов
/ 14 ноября 2018

У меня есть карта структуры карт, например:

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 голосов
/ 14 ноября 2018

К сожалению, если вы хотите продолжить потоковый подход, неизбежно для создания промежуточного объекта некоторого типа, т.е. Triple, или AbstractMap.SimpleEntry, или любого другого применимого типа.

По сути, вы ищете что-то вроде анонимных типов в C #, то есть вы можете просто отобразить на

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

, а затем немедленно получить доступ к тем в фазе groupingBy и toMap.

В 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.

Единственное преимущество в том, что вам не нужно предварительно определять пользовательский класс.

0 голосов
/ 14 ноября 2018

Некоторые вещи проще сделать без потоков:

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)));
...