Использование потоков Java 8, как преобразовать карту> к карте>? - PullRequest
0 голосов
/ 12 мая 2018

Итак, у меня есть Map<String, Map<String, List<Person>>>, и я хочу преобразовать его в Map<Integer, Map<String, Integer>>, где первый ключ Integer представляет числа 1,2,3 ..... (индекс текущей записи взят из первой карты)а второе целое число дает мне размер List<Person>.Строка на внутренней карте остается прежней ....

Сначала я просто попытался заменить второе целое число на карте размером списка, но оно не работает .....

Map<String, Map<String, List<Person>>> map2 =...
Map<String, Map<String, Integer>> map = map2.entrySet().stream().collect(
                Collectors.groupingBy(p -> p.getKey(), Collectors.toMap(p -> p.getValue().getKey(), p->p.getValue().values().size())));

Ответы [ 2 ]

0 голосов
/ 12 мая 2018

По определению, карта не имеет индекса.Возможно, вы пытаетесь присвоить элементам карты номер, начиная с 1, в соответствии с порядком вставки .Если вы используете LinkedHashMap, есть способ сделать это.

Однако HashMap не дает никаких гарантий относительно порядка карты.Кроме того, это не гарантирует, что заказ останется постоянным с течением времени;Таким образом, присвоение этим записям нумерации не всегда приведет к ожидаемому результату.

Тем не менее, вы можете захотеть пронумеровать записи на карте только от 1 до n, где n - это размеркарты и не относятся к порядку вставки записей, как указано выше, т.е. первая вставленная запись не обязательно должна быть пронумерована как 1, а вторая вставленная запись не обязательно должна быть пронумерована как 2 и т. д.

Теперь, к решению:

Вы можете иметь List<Map<String, Integer>> в качестве временного набора результатов, и когда вам нужна нумерация записей, просто зациклите элементы и получите нумерацию с помощью i + 1 где i - управляющая переменная.

пример, предполагая, что у нас есть этот список:

List<Map<String, Integer>> temporaryResult = myMap.values()
            .stream()
            .map(a -> a.entrySet()
                    .stream()
                    .collect(Collectors.toMap(Map.Entry::getKey,
                            c -> c.getValue().size()))
            )
            .collect(Collectors.toList());

тогда мы можем получить Map<Integer, Map<String, Integer>> с:

  Map<Integer, Map<String, Integer>> resultSet =
                IntStream.range(0, temporaryResult.size())
                .mapToObj(i -> new AbstractMap.SimpleEntry<>(i + 1,
                        temporaryResult.get(i)))
                .collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey,
                        AbstractMap.SimpleEntry::getValue));

Примечание -

  1. Если нумерация должна основываться на порядке вставки, этот код даст ожидаемый результат, только если используемая карта поддерживает порядок вставки.
  2. Если онемениеering не обязательно основан на порядке вставки записей в карту, тогда это решение будет работать независимо от используемой реализации карты.
0 голосов
/ 12 мая 2018

Я бы использовал список, чтобы сохранить порядок записей на исходной карте, нет необходимости хранить индекс в качестве ключа карты.

Это будет проходить через все значения вашего начальногоmap, сопоставьте Map с ожидаемым с помощью size() списка и соберите все в List

List<Map<String, Integer>> map = 
    map2.values()
        .stream()
        .map(m-> m.entrySet()
                  .stream()
                  .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().size())))
        .collect(Collectors.toList());

Если вам действительно нужен Map по любой причине, следующий код тоже должен работать

int i = 1;
Map<Integer, Map<String, Integer>> newMap = new HashMap<>();
for (Map.Entry entry : map2.entrySet()) {
    Map<String, Integer> map = entry.value().entrySet()
              .stream()
              .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().size())
    newMap.put(i++, map);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...