Java объединить два map

Слияние двух карт с Java 8

В этом кратком руководствеwe’ll demonstrate how to merge two maps using the Java 8 capabilities.

Чтобы быть более конкретным, мы рассмотрим различные сценарии объединения, включая карты с повторяющимися записями.

2. инициализация

Для начала определим два экземпляраMap:

private static Map map1 = new HashMap<>(); private static Map map2 = new HashMap<>();

КлассEmployee выглядит так:

Затем мы можем поместить некоторые данные в экземплярыMap:

Employee employee1 = new Employee(1L, "Henry"); map1.put(employee1.getName(), employee1); Employee employee2 = new Employee(22L, "Annie"); map1.put(employee2.getName(), employee2); Employee employee3 = new Employee(8L, "John"); map1.put(employee3.getName(), employee3); Employee employee4 = new Employee(2L, "George"); map2.put(employee4.getName(), employee4); Employee employee5 = new Employee(3L, "Henry"); map2.put(employee5.getName(), employee5);

Обратите внимание, что у нас есть одинаковые ключи для записейemployee1 иemployee5 на наших картах, которые мы будем использовать позже.

3. Map.merge()с

Java 8 adds a new merge() function into the java.util.Map interface.

Вот как работает функцияmerge(): если указанный ключ еще не связан со значением или значение равно нулю, он связывает ключ с заданным значением.

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

Во-первых, давайте создадим новыйHashMap, скопировав все записи изmap1:

Map map3 = new HashMap<>(map1);

Затем давайте представим функциюmerge() вместе с правилом слияния:

map3.merge(key, value, (v1, v2) -> new Employee(v1.getId(),v2.getName())

Наконец, мы переберемmap2 и объединим записи вmap3:

map2.forEach( (key, value) -> map3.merge(key, value, (v1, v2) -> new Employee(v1.getId(),v2.getName())));

Запустим программу и распечатаем содержимоеmap3:

John=Employee Annie=Employee George=Employee Henry=Employee

В результатеour combined Map has all the elements of the previous HashMap entries. Entries with duplicate keys have been merged into one entry.

Также мы заметили, что объектEmployee последней записи имеетid изmap1, а значение выбирается изmap2.

Это из-за правила, которое мы определили в нашей функции слияния:

(v1, v2) -> new Employee(v1.getId(), v2.getName())

4. Stream.concat()с

APIStream в Java 8 также может предоставить простое решение нашей проблемы. Во-первых,we need to combine our Map instances into one Stream. Именно это и делает операцияStream.concat():

Stream combined = Stream.concat(map1.entrySet().stream(), map2.entrySet().stream());

Здесь мы передаем наборы записей карты в качестве параметров. Next, we need to collect our result into a new Map. Для этого мы можем использоватьCollectors.toMap():

Map result = combined.collect( Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

В результате сборщик будет использовать существующие ключи и значения наших карт. Но это решение далеко не идеально. Как только наш сборщик встречает записи с повторяющимися ключами, он выдастIllegalStateException.

Чтобы решить эту проблему, мы просто добавляем третий лямбда-параметр «слияния» в наш сборщик:

(value1, value2) -> new Employee(value2.getId(), value1.getName())

Он будет использовать лямбда-выражение каждый раз, когда обнаруживается повторяющийся ключ.

Наконец, собрав все воедино:

Map result = Stream.concat(map1.entrySet().stream(), map2.entrySet().stream()) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (value1, value2) -> new Employee(value2.getId(), value1.getName())));

Наконец, давайте запустим код и посмотрим на результаты:

George=Employee John=Employee Annie=Employee Henry=Employee

Как мы видим, повторяющиеся записи с ключом“Henry” были объединены в новую пару ключ-значение, гдеthe id of the new Employee was picked from the map2 and the value from map1.

5. Stream.of()

Чтобы продолжить использование APIStream, мы можем превратить наши экземплярыMap в единый поток с помощьюStream.of().

Здесь нам не нужно создавать дополнительную коллекцию для работы с потоками:

Map map3 = Stream.of(map1, map2) .flatMap(map -> map.entrySet().stream()) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> new Employee(v1.getId(), v2.getName())));

Во-первых,we transform map1 and map2 into a single stream. Далее мы конвертируем поток в карту. Как мы видим, последний аргументtoMap() — это функция слияния. Он решает проблему дублирования ключей, выбирая поле id из записиv1 и имя изv2.

Напечатанный экземплярmap3 после запуска программы:

George=Employee John=Employee Annie=Employee Henry=Employee

6. Простая потоковая передача

Кроме того, мы можем использовать спайплайнstream() для сборки записей на карте. Приведенный ниже фрагмент кода демонстрирует, как добавить записи изmap2 иmap1, игнорируя повторяющиеся записи:

Map map3 = map2.entrySet() .stream() .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> new Employee(v1.getId(), v2.getName()), () -> new HashMap<>(map1)));

Как мы ожидаем, результаты после слияния:

, Annie=Employee, George=Employee, Henry=Employee>

7. StreamExс

В дополнение к решениям, предоставляемым JDK, мы также можем использовать популярную библиотекуStreamEx .

Проще говоря,StreamEx is an enhancement for the Stream API и предоставляет множество дополнительных полезных методов. Мы будем использоватьEntryStream instance to operate on key-value pairs:

Map map3 = EntryStream.of(map1) .append(EntryStream.of(map2)) .toMap((e1, e2) -> e1);

Идея состоит в том, чтобы объединить потоки наших карт в одну. Затем мы собираем записи в новый экземплярmap3. Важно отметить, что выражение(e1, e2) → e1 помогает определить правило работы с повторяющимися ключами. Без него наш код выдастIllegalStateException.

, John=Employee, Annie=Employee, Henry=Employee>

8. Резюме

В этой короткой статье мы узнали о различных способах объединения карт в Java 8. В частности,we used Map.merge(), Stream API, StreamEx library.

Как всегда, код, использованный во время обсуждения, можно найтиover on GitHub.

Источник

Объединить две карты в Java

В этом посте мы обсудим, как объединить две карты одного типа в Java. Решение возвращает новую карту, содержащую все сопоставления на обеих картах. Операция слияния будет обрабатывать общие ключи, присутствующие в обеих картах.

1. Использование putAll() метод

Простое решение — использовать Map.putAll() метод для копирования всех сопоставлений с исходной карты на другую карту.

Обратите внимание, что если ключ k существует на обеих картах, значение в hm2 перезапишет значение в hm1 . т.е., map[k] = hm2[k] . Например,

Мы можем избежать лишнего вызова putAll() метод, передав первую карту в HashMap конструктор.

Если вам нужно добавить содержимое карты hm1 для отображения hm2 , вы можете просто сделать:

2. Использование Guava

Guava также предоставляет конструктор для создания неизменяемых экземпляров карты с использованием putAll() метод, последовательные вызовы которого могут быть объединены в цепочку:

3. Использование Java 8

В Java 8 и выше вы можете получить поток элементов обеих карт и вызвать Collectors.toMap() чтобы собрать все элементы карты в новую карту, применив к ней указанные функции отображения, чтобы помочь идентифицировать ключи и значения. Это показано ниже:

Приведенный выше код выдает java.lang.IllegalStateException если дубликат ключа присутствует в обеих картах. Чтобы справиться с этим, предоставьте функцию слияния для разрешения конфликтов между значениями, связанными с одним и тем же ключом.

Следующий код обеспечивает BinaryOperator для объединения значений повторяющихся ключей, где старое значение имеет приоритет над новым значением в потоке.

Источник

How to merge two maps in Java

There are multiple ways to merge or join two instances of the HashMap class in Java. In this article, you’ll learn to join maps with and without handling duplicate keys.

Let us say you have got the following two HashMap objects that you want to combine:

MapString, Integer> map1 = new HashMap>(); map1.put("A", 1); map1.put("B", 2); map1.put("C", 3); map1.put("F", 4); MapString, Integer> map2 = new HashMap>(); map2.put("A", 3); map2.put("B", 4); map2.put("D", 5); 

The Map.putAll() method provides a quick and simple solution to merge two maps. This method copies all key-value pairs from the second map to the first map. Since a HashMap object can not store duplicate keys, the Map.putAll() method override the value of duplicate keys in the first map with values from the second map.

// Merge second map with first map map1.putAll(map2); // Print new map System.out.println(map1); 

The Map.merge() method was introduced in Java 8 and is useful for joining maps with duplicate keys. This method takes three arguments as input: key, value, and a remapping function to merge values for duplicate keys. If the specified key is not already associated with a value or is associated with null , the Map.merge() method associates it with the given non-null value. Otherwise, the Map.merge() method replaces the value with the results of the given remapping function. If the result of the remapping function is null , it removes the key altogether. The following example demonstrates how you can combine the values of duplicate keys using the remapping function of Map.merge() :

// Merge second map with first map map2.forEach((key, value) -> map1.merge(key, value, (v1, v2) -> v1 + v2) ); // Print new map System.out.println(map1); // 

Notice the values of key B . It had value 2 in map1 and value 4 in map2 . After the merge, it has a combined value of 6 in the merged map. The remapping function allows you to write any merge logic that suits your needs.

The Stream.concat() method from the Stream API in Java 8 can also be used to combine two maps. As the name suggests, the Stream.concat() method combines the Map instances into one Stream object:

StreamMap.EntryString, Integer>> combined = Stream.concat(map1.entrySet().stream(), map2.entrySet().stream()); 
MapString, Integer> merged = combined.collect( Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); 

The above solution works fine as long as there are no duplicate keys. If it encounters any duplicate entry, it will throw an IllegalStateException exception. To handle duplicate entries, you can pass a merger function as a third parameter to the collector:

MapString, Integer> merged = combined.collect( Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v1 + v2)); // Print new map System.out.println(merged); // 

Stream.of() is another method from the Stream API that can be used to merge two maps in Java 9 and above:

// Merge the second map with the first map MapString, Integer> merged = Stream.of(map1, map2) .flatMap(map -> map.entrySet().stream()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v1 + v2)); // Print new map System.out.println(merged); // 

In the above example, we first transform map1 and map2 into a unified stream with the help of Stream.of() and Stream.flatMap() methods. Next, we convert the stream into a map using a collector function. ✌️ Like this article? Follow me on Twitter and LinkedIn. You can also subscribe to RSS Feed.

You might also like.

Источник

Читайте также:  Язык программирования питон выучить
Оцените статью