Рубрики
Без рубрики

Сравнение двух хэш-карт на Java

Узнайте, как сравнить два HashMaps на Java, а также найти различия между ними

Автор оригинала: baeldung.

Сравнение двух хэш-карт на Java

1. Обзор

В этом учебнике мы собираемся изучить различные способы сравнения двух HashMaps в Java .

Мы обсудим несколько способов проверить, если два HashMaps похожи. Мы также будем использовать Java 8 Stream API и Guava, чтобы получить подробные различия между различными HashMaps .

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

Во-первых, мы будем использовать Map.equals () чтобы проверить, если два HashMaps имеют те же записи:

@Test
public void whenCompareTwoHashMapsUsingEquals_thenSuccess() {
    Map asiaCapital1 = new HashMap();
    asiaCapital1.put("Japan", "Tokyo");
    asiaCapital1.put("South Korea", "Seoul");

    Map asiaCapital2 = new HashMap();
    asiaCapital2.put("South Korea", "Seoul");
    asiaCapital2.put("Japan", "Tokyo");

    Map asiaCapital3 = new HashMap();
    asiaCapital3.put("Japan", "Tokyo");
    asiaCapital3.put("China", "Beijing");

    assertTrue(asiaCapital1.equals(asiaCapital2));
    assertFalse(asiaCapital1.equals(asiaCapital3));
}

Здесь мы создаем три HashMap объектов и добавление записей. Тогда мы используем Map.equals () чтобы проверить, если два HashMaps имеют те же записи.

Так, как Map.equals () работы путем сравнения ключей и значений с помощью Object.equals () метод . Это означает, что он работает только тогда, когда как ключевые, так и ценностные объекты равны () правильно.

Например, Map.equals () не работает, когда тип значения массив, как равны () метод сравнивает идентичность, а не содержимое массива:

@Test
public void whenCompareTwoHashMapsWithArrayValuesUsingEquals_thenFail() {
    Map asiaCity1 = new HashMap();
    asiaCity1.put("Japan", new String[] { "Tokyo", "Osaka" });
    asiaCity1.put("South Korea", new String[] { "Seoul", "Busan" });

    Map asiaCity2 = new HashMap();
    asiaCity2.put("South Korea", new String[] { "Seoul", "Busan" });
    asiaCity2.put("Japan", new String[] { "Tokyo", "Osaka" });

    assertFalse(asiaCity1.equals(asiaCity2));
}

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

Мы также можем внедрить наш собственный метод для сравнения ХэшМэпс с помощью Java 8 поток API:

private boolean areEqual(Map first, Map second) {
    if (first.size() != second.size()) {
        return false;
    }

    return first.entrySet().stream()
      .allMatch(e -> e.getValue().equals(second.get(e.getKey())));
}

Для простоты мы внедрили areEqual () метод, который мы теперь можем использовать для сравнения Объекты HashMap :

@Test
public void whenCompareTwoHashMapsUsingStreamAPI_thenSuccess() {
    assertTrue(areEqual(asiaCapital1, asiaCapital2));
    assertFalse(areEqual(asiaCapital1, asiaCapital3));
}

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

private boolean areEqualWithArrayValue(Map first, Map second) {
    if (first.size() != second.size()) {
        return false;
    }

    return first.entrySet().stream()
      .allMatch(e -> Arrays.equals(e.getValue(), second.get(e.getKey())));
}

В отличие от Map.equals () , наш собственный метод будет успешно сравнивать HashMaps с значениями массива:

@Test
public void whenCompareTwoHashMapsWithArrayValuesUsingStreamAPI_thenSuccess() {
    assertTrue(areEqualWithArrayValue(asiaCity1, asiaCity2)); 
    assertFalse(areEqualWithArrayValue(asiaCity1, asiaCity3));
}

4. Сравнение ключей и значений HashMap

Далее давайте посмотрим, как сравнить два HashMap ключей и их соответствующих значений.

4.1. Сравнение ключей HashMap

Во-первых, мы можем проверить, если два HashMaps имеют те же ключи, просто сравнивая их KeySet () :

@Test
public void whenCompareTwoHashMapKeys_thenSuccess() {
    assertTrue(asiaCapital1.keySet().equals(asiaCapital2.keySet())); 
    assertFalse(asiaCapital1.keySet().equals(asiaCapital3.keySet()));
}

4.2. Сравнение значений HashMap

Далее, мы увидим, как сравнить HashMap значения один за другим.

Мы реализуем простой метод проверки того, какие ключи имеют одинаковое значение как в HashMaps с помощью Поток API:

private Map areEqualKeyValues(Map first, Map second) {
    return first.entrySet().stream()
      .collect(Collectors.toMap(e -> e.getKey(), 
        e -> e.getValue().equals(second.get(e.getKey()))));
}

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

@Test
public void whenCompareTwoHashMapKeyValuesUsingStreamAPI_thenSuccess() {
    Map asiaCapital3 = new HashMap();
    asiaCapital3.put("Japan", "Tokyo");
    asiaCapital3.put("South Korea", "Seoul");
    asiaCapital3.put("China", "Beijing");

    Map asiaCapital4 = new HashMap();
    asiaCapital4.put("South Korea", "Seoul");
    asiaCapital4.put("Japan", "Osaka");
    asiaCapital4.put("China", "Beijing");

    Map result = areEqualKeyValues(asiaCapital3, asiaCapital4);

    assertEquals(3, result.size());
    assertThat(result, hasEntry("Japan", false));
    assertThat(result, hasEntry("South Korea", true));
    assertThat(result, hasEntry("China", true));
}

5. Разница в карте с использованием Гуавы

Наконец, мы увидим как получить подробную разницу между двумя HashMaps с помощью Гуавы Maps.difference().

Этот метод возвращает MapDifference объект, который имеет ряд полезных методов для анализа разницы между Карты. Давайте посмотрим на некоторые из них.

5.1. MapDifference.entriesDiffering()

Во-первых, мы общие ключи, которые имеют различные значения в каждом HashMap с помощью MapDifference.entriesDiffering () :

@Test
public void givenDifferentMaps_whenGetDiffUsingGuava_thenSuccess() {
    Map asia1 = new HashMap();
    asia1.put("Japan", "Tokyo");
    asia1.put("South Korea", "Seoul");
    asia1.put("India", "New Delhi");

    Map asia2 = new HashMap();
    asia2.put("Japan", "Tokyo");
    asia2.put("China", "Beijing");
    asia2.put("India", "Delhi");

    MapDifference diff = Maps.difference(asia1, asia2);
    Map> entriesDiffering = diff.entriesDiffering();

    assertFalse(diff.areEqual());
    assertEquals(1, entriesDiffering.size());
    assertThat(entriesDiffering, hasKey("India"));
    assertEquals("New Delhi", entriesDiffering.get("India").leftValue());
    assertEquals("Delhi", entriesDiffering.get("India").rightValue());
}

записиРазумные () метод возвращает новую Карта который содержит набор общих ключей и ЗначениеРазумность объектов как набора значений.

Каждая ЗначениеРазумность объект имеет leftValue () и rightValue () методы, которые возвращают значения в двух Карты соответственно.

5.2. MapDifference.entriesOnlyOnRight() и MapDifference.entriesOnLeft ()

Затем мы можем получить записи, которые существуют только в одном HashMap с помощью MapDifference.entriesOnlyOnRight () и MapDifference.entriesOnlyOnLeft ():

@Test
public void givenDifferentMaps_whenGetEntriesOnOneSideUsingGuava_thenSuccess() {
    MapDifference diff = Maps.difference(asia1, asia2);
    Map entriesOnlyOnRight = diff.entriesOnlyOnRight();
    Map entriesOnlyOnLeft = diff.entriesOnlyOnLeft();
    
    assertEquals(1, entriesOnlyOnRight.size());
    assertEquals(1, entriesOnlyOnLeft.size());
    assertThat(entriesOnlyOnRight, hasEntry("China", "Beijing"));
    assertThat(entriesOnlyOnLeft, hasEntry("South Korea", "Seoul"));
}

5.3. MapDifference.entriesInCommon()

Далее, Мы получим общие записи, используя MapDifference.entriesInCommon():

@Test
public void givenDifferentMaps_whenGetCommonEntriesUsingGuava_thenSuccess() {
    MapDifference diff = Maps.difference(asia1, asia2);
    Map entriesInCommon = diff.entriesInCommon();

    assertEquals(1, entriesInCommon.size());
    assertThat(entriesInCommon, hasEntry("Japan", "Tokyo"));
}

5.4. Настройка Maps.difference() Поведение

С Maps.difference () использовать равны () и хэш-код () по умолчанию для сравнения записей, он не будет работать для объектов, которые не реализуют их должным образом:

@Test
public void givenSimilarMapsWithArrayValue_whenCompareUsingGuava_thenFail() {
    MapDifference diff = Maps.difference(asiaCity1, asiaCity2);
    assertFalse(diff.areEqual());
}

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

Например, мы определим Эквивалентность для типа Струнный для сравнения Струнный ценности в нашем HashMaps как нам нравится:

@Test
public void givenSimilarMapsWithArrayValue_whenCompareUsingGuavaEquivalence_thenSuccess() {
    Equivalence eq = new Equivalence() {
        @Override
        protected boolean doEquivalent(String[] a, String[] b) {
            return Arrays.equals(a, b);
        }

        @Override
        protected int doHash(String[] value) {
            return value.hashCode();
        }
    };

    MapDifference diff = Maps.difference(asiaCity1, asiaCity2, eq);
    assertTrue(diff.areEqual());

    diff = Maps.difference(asiaCity1, asiaCity3, eq); 
    assertFalse(diff.areEqual());
}

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

В этой статье мы обсудили различные способы сравнения HashMaps на Яве. Мы узнали несколько способов проверить, если два HashMaps равны и как получить подробную разницу, а также.

Полный исходный код доступен более на GitHub .