Потоки Java 8 - объединить коллекцию карт - PullRequest
2 голосов
/ 07 марта 2019

Допустим, у меня есть метод со следующей сигнатурой:

Map<String, String> merge (String[][] ... maps)

Требуется (вариативное) число двумерных массивов, представляющих отображения, например:

        String[][] m1 = new String[][] {
            {"k1", "a"},
            {"k2", "b"}
        };

        String[][] m2 = new String[][] {
            {"k1", "a"},
            {"k2", "b"},
            {"k3", "c"}   
        };

        String[][] m3 = new String[][] {
            {"k1", "x"},
            {"k2", "b"}
        };

Теперь я могу объединить любые две карты слева направо следующим образом:

 Map<String, String> m1 = Stream.of(map1).collect(Collectors.toMap(k -> k[0], v -> v[1]));
 Map<String, String> m2 = Stream.of(map2).collect(Collectors.toMap(k -> k[0], v -> Optional.ofNullable(v[1]).orElse("null")));
 m1.forEach((key, value) -> m2.merge(key, value, (v1, v2) -> v1));

Но как мне слить переменное число таких карт-массивов, чтобы после передачи m1, m2, m3как определено выше, результат:

        String[][] m3 = new String[][] {
            {"k1", "x"},
            {"k2", "b"}
            {"k3", "c"}   
        };

Ответы [ 2 ]

6 голосов
/ 07 марта 2019

Это довольно просто, если я правильно понимаю ваш вопрос.Вы просто записываете все записи и собираете их на карту с помощью функции слияния, которая выбирает более позднее значение:

Map<String, String> merge (String[][] ... maps) {
    return Arrays.stream(maps)
            .flatMap(Arrays::stream)
            .collect(Collectors.toMap(a -> a[0], a -> a[1], (a, b) -> b));
}

Если вы хотите преобразовать его обратно в массив, вы можете сделать

String[][] m3 = merge(maps)
        .entrySet()
        .stream()
        .map(e -> new String[] { e.getKey(), e.getValue() })
        .toArray(String[][]::new);
3 голосов
/ 07 марта 2019
Map<String, String> merge(String[][]... maps) {
    return Stream.of(maps)
            .flatMap(Arrays::stream)          //flatten all maps into a single stream
            .map(s -> Map.entry(s[0], s[1]))  //convert array to Entry
            .collect(Collectors.toMap(Map.Entry::getKey,
                    Map.Entry::getValue,
                    (o1, o2) -> o2));
}

Редактировать : Нет необходимости конвертировать в Entry.Мы можем напрямую собирать на карту, как показывал @shmosel.

...