Как сравнить две карты в Java

Изучите различные способы сравнения двух хэш-карт в Java по ключам, значениям и парам ключ-значение. Также научитесь сравнивать карты, разрешая или ограничивая дублирующиеся значения.

1. Сравните карты для одинаковых ключей и значений

1.1 Использование Map.equals()

По умолчанию метод HashMap.equals() сравнивает два хэш-файла по парам ключ-значение. Это означает, что оба экземпляра HashMap должны иметь абсолютно одинаковые пары ключ-значение и оба должны быть одинакового размера. Порядок пар ключ-значение может быть разным и не играет роли при сравнении.

Map<String, Integer> map1 = Map.of("A", 1, "B", 2);Map<String, Integer> map2 = Map.of("A", 1, "B", 2);Map<String, Integer> map3 = Map.of("C", 1, "D", 2);Assertions.assertTrue( map1.equals(map2) );Assertions.assertFalse( map1.equals(map3) );

1.2 Сравнение карт со значениями типа массива

Стоит отметить, что ключи и значения Map сравниваются с использованием их метода equals(), поэтому объекты key и value должны правильно реализовать метод equals(), чтобы дать согласованный результат. Например, если значение Map является массивом, то сравнение не будет работать, так как array.equals() сравнивает идентификатор объекта, а не содержимое массива.

Map<String, Integer[]> map4 = Map.of("A", new Integer[]{1}, "B", new Integer[]{2});Map<String, Integer[]> map5 = Map.of("A", new Integer[]{1}, "B", new Integer[]{2});Assertions.assertFalse(map4.equals(map5));

В таком случае мы можем создать собственный метод для сравнения содержимого массива с помощью метода Arrays.equals().

private static boolean checkEqualMapsWithArrayTypeValues(Map<String, Integer[]> firstMap,Map<String, Integer[]> secondMap) {if(firstMap.size() != secondMap.size())return false;return firstMap.entrySet().stream().allMatch(e -> Arrays.equals(e.getValue(), secondMap.get(e.getKey())));}

Теперь сравнение карт проверит содержимое массива и выдаст правильный результат.

Map<String, Integer[]> map4 = Map.of("A", new Integer[]{1}, "B", new Integer[]{2});Map<String, Integer[]> map5 = Map.of("A", new Integer[]{1}, "B", new Integer[]{2});Assertions.assertFalse( checkEqualMapsWithArrayTypeValues(map4, map5) );

2. Сравнение ключей карты

Мы можем сравнить две Карты, чтобы определить, есть ли у них одинаковые ключи или нет. Или мы можем найти недостающие ключи во второй Карте, если это необходимо.

2.1. Обе карты имеют одинаковые ключи

Если мы хотим сравнить хэш-карты по ключам, то есть две хэш-карты будут равны, если у них одинаковый набор ключей, мы можем использовать функцию HashMap.keySet(). Она возвращает все ключи карты в HashSet.

Затем мы можем сравнить HashSet для обеих карт с помощью метода Set.equals(). Он возвращает true, если два набора имеют одинаковый размер, и каждый элемент указанного набора содержится в другом наборе.

Map<String, Integer> map1 = Map.of("A", 1, "B", 2);Map<String, Integer> map2 = Map.of("A", 1, "B", 2);Assertions.assertTrue( map1.keySet().equals(map2.keySet()) );Map<String, Integer> map3 = Map.of("A", 1, "B", 2, "C", 3, "D", 4);Assertions.assertFalse( map1.keySet().equals(map6.keySet()) );

2.2. Разница в ключах карты

Нам может быть интересно узнать, какие дополнительные ключи есть у первой хэш-карты по сравнению со второй. Чтобы получить эту разницу, выполните объединение ключей из обеих хэш-карт, а затем удалите все ключи, присутствующие в первой хэш-карте.

Программа на Java для поиска разницы между двумя хэш-картами.

HashSet<String> unionKeys = new HashSet<>(map1.keySet());unionKeys.addAll(map3.keySet());unionKeys.removeAll(map1.keySet());Assertions.assertEquals(Set.of("C", "D"), unionKeys );

2. Сравнение значений карты

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

3.1. Допускаются повторяющиеся значения.

Добавьте все значения из HashMap.values() в ArrayList для обеих карт. Теперь сравните оба списка массивов на предмет эквивалентности.

new ArrayList<>( map1.values() ).equals(new ArrayList<>( map2.values() )); //truenew ArrayList<>( map1.values() ).equals(new ArrayList<>( map3.values() )); //false

3.2. Повторяющиеся значения НЕ допускаются.

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

new HashSet<>( map1.values() ).equals(new HashSet<>( map2.values() )); //truenew HashSet<>( map1.values() ).equals(new HashSet<>( map3.values() )); //true

4. Разница в карте с гуавой

Если нам интересно найти разницу между двумя картами, то Guava предоставляет отличный API Maps.difference().

<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>31.1-jre</version></dependency>

Map.difference() возвращает экземпляр класса MapDifference. Проверяя MapDifference, мы можем найти разницу в Maps несколькими способами.

MapDifference diff = Maps.difference(map1, map2);

Давайте посмотрим на API в действии на простом примере. У map1 и map2 есть некоторые общие записи, и у каждой карты есть несколько различных записей.

Map<String, Integer> map1 = Map.of("A", 1, "B", 2, "E", 5, "F", 6);Map<String, Integer> map2 = Map.of("A", 1, "B", 2, "C", 3, "D", 4);MapDifference<String, Integer> diff = Maps.difference(map1, map2);Assertions.assertFalse(diff.areEqual());Assertions.assertEquals(Map.of("A", 1, "B", 2), diff.entriesInCommon());Assertions.assertEquals(Map.of("E", 5, "F", 6), diff.entriesOnlyOnLeft());Assertions.assertEquals(Map.of("C", 3, "D", 4), diff.entriesOnlyOnRight());

5. Заключение

В этом коротком уроке мы научились сравнивать две карты на предмет равенства их записей, ключей и значений. Мы также научились находить различия в картах с помощью простых API Java, а также API MapDifference от Guava.

Напишите мне ваши вопросы, связанные со сравнением хэш-карт в Java.

Исходный код на Github

Прокрутить вверх