Объединить список карт с повторяющимися ключами

У меня есть список HashMap<Integer, ArrayList<String>>, и я хотел бы объединить их в цикле. Проблема в том, что ключ каждой карты начинается с 0, поэтому ключи будут дублироваться. putAll() не работает, так как он переопределяет клавиши и всегда дает мне последнюю карту.

Я видел примеры объединения двух карт с помощью Stream, но в моем случае может быть больше двух карт. Я пытаюсь создать объединенную карту с инкрементным ключом. Например:

Допустим, у меня в списке 2 карты (может быть больше), и оба ключа начинаются с 0, но заканчиваются на разные значения.

1-я карта, ключ начинается с 0 и заканчивается на 10

2 карта, ключ начинается с 0 заканчивается на 15

Можно ли добавить вторую карту с ключом начиная с 11? В конце концов, мне нужна объединенная карта, в которой первый ключ начинается с 0, а последний ключ заканчивается на 25.

HashMap не допускает дублирования ключей, поэтому ключи будут переопределены. Чего именно вы пытаетесь достичь здесь в качестве вывода?

Raja Shekar 11.12.2020 12:15

Я предполагаю, что вы имеете в виду объединение строковых списков записей карты с одним и тем же ключом?

stridecolossus 11.12.2020 12:16

@RajaShekar отредактировал вопрос, чтобы уточнить, что мне нужно. Ключи должны быть инкрементными.

Cugomastik 11.12.2020 12:28
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
3
1 358
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Я бы перебирал любое количество карт, которые у вас есть, а затем для каждой карты, которую вы хотите объединить, перебирал записи. Для каждой записи вы можете использовать calculateIfAbsent , чтобы условно создать пустой список для ключа, а затем вызвать addAll для значения. Например.:

List<Map<Integer, List<String>>> maps = List.of(
        Map.of(1, List.of("hello")),
        Map.of(2, List.of("world")),
        Map.of(1, List.of("a"), 2, List.of("b"))
);

Map<Integer, List<String>> combined = new HashMap<>();
for (Map<Integer, List<String>> map : maps) {
    for (Map.Entry<Integer, List<String>> e : map.entrySet()) {
        combined.computeIfAbsent(e.getKey(), k -> new ArrayList<>()).addAll(e.getValue());
    }
}

Привет Мурейник, большое спасибо за ваш ответ. К сожалению, карты не объединены, и я все еще получаю последнюю карту.

Cugomastik 11.12.2020 13:07

@Cugomastik Тогда я предлагаю предоставить минимальный воспроизводимый пример в вопросе. Приведенный выше код определенно объединяет карты в одну (работает в JShell).

Slaw 11.12.2020 13:15

Если вы предпочитаете потоковый подход

Map<Integer, List<String>> m1;
Map<Integer, List<String>> m2;
Map<Integer, List<String>> m3;

Map<Integer, List<String>> combined = new HashMap<>();
Stream
    .of(m1, m2, m3)
    .flatMap(m -> m.entrySet().stream())
    .forEach(e -> combined.computeIfAbsent(e.getKey(), k -> new ArrayList<>())
            .addAll(e.getValue()));

Спасибо за ваш ответ, но что, если нужно объединить 50 карт? Можно ли его использовать в цикле?

Cugomastik 11.12.2020 12:47

В случае 50, я ожидаю, что у вас будет их список. Затем вы можете транслировать список. List<Map<Integer, List<String>>> maps. Вы можете использовать maps.stream(), а затем остальную часть кода.

moh ro 11.12.2020 12:49

Большое спасибо за ваш ответ. Я адаптировал код и попробовал его со списком карт, но получил только последнюю карту.

Cugomastik 11.12.2020 13:08

В приведенном выше примере вы найдете все записи на объединенной карте.

moh ro 11.12.2020 13:21
Ответ принят как подходящий

Предполагая, что у вас есть список карт, где ключи каждой карты являются целыми числами в диапазоне [0-k], [0-n], [0, r] ..., и ваша результирующая карта должна иметь ключ, установленный в диапазоне [0 - (k+n+r..)], должно работать что-то вроде следующего:

public static void main(String[] args) throws IOException {
   //example list of maps
   List<Map<Integer,List<String>>> mapList = List.of(
           Map.of( 0,List.of("foo","foo"), 
                   1,List.of("bar","bar"), 
                   2,List.of("baz","baz")),
           Map.of( 0,List.of("doo","doo"), 
                   1,List.of("gee","gee"), 
                   2,List.of("woo","woo")),
           Map.of( 0,List.of("cab","cab"), 
                   1,List.of("kii","kii"), 
                   2,List.of("taa","taa"))
   );
   AtomicInteger ai = new AtomicInteger();
   Map<Integer,List<String>> result = 
           mapList.stream()
                   .flatMap(map -> map.values().stream())
                   .collect(Collectors.toMap(list -> ai.getAndIncrement(), Function.identity()));
   result.forEach((k,v) ->{
       System.out.println(k + " : " + v);
   });
}

@Cugomastik Добро пожаловать. Рад, что смог помочь

Eritrean 11.12.2020 13:50

Я знаю, что вы просили карту, но на основе вашего объяснения вашего окончательного решения и того факта, что ваши ключи теперь представляют собой последовательные целые числа, начинающиеся с 0, вы могли бы создать просто List<List<String>>. В этом случае вы можете сделать это следующим образом:

List<List<String>> result = mapList.stream()
               .flatMap(map->map.values().stream())
               .collect(Collectors.toList());                      

Другие вопросы по теме