Membandingkan Dua HashMaps di Java

1. Gambaran keseluruhan

Dalam tutorial ini, kita akan meneroka pelbagai cara untuk membandingkan dua HashMaps di Java .

Kami akan membincangkan pelbagai cara untuk memeriksa sama ada dua HashMaps serupa. Kami juga akan menggunakan Java 8 Stream API dan Jambu untuk mendapatkan perbezaan terperinci antara HashMaps yang berbeza .

2. Menggunakan Peta.sama ()

Pertama, kami akan menggunakan Map.equals () untuk memeriksa sama ada dua HashMaps mempunyai entri yang sama:

@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)); }

Di sini, kami membuat tiga objek HashMap dan menambah entri. Kemudian kami menggunakan Map.equals () untuk memeriksa sama ada dua HashMaps mempunyai entri yang sama.

Cara yang Map.equals () berfungsi ialah dengan membandingkan kunci dan nilai menggunakan () Object.equals kaedah . Ini bermaksud ia hanya berfungsi apabila kedua-dua objek kunci dan nilai melaksanakan sama dengan () dengan betul.

Sebagai contoh, Map.equals () tidak berfungsi apabila jenis nilai adalah array, kerana kaedah sama dengan () kaedah membandingkan identiti dan bukan kandungan array:

@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. Menggunakan Java Stream API

Kami juga dapat menerapkan kaedah kami sendiri untuk membandingkan HashMaps menggunakan Java 8 Stream 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()))); }

Untuk kesederhanaan, kami menerapkan kaedah areEqual () yang kini dapat kami gunakan untuk membandingkan objek HashMap :

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

Tetapi kita juga dapat menyesuaikan kaedah kita sendiri iaituEqualWithArrayValue () untuk menangani nilai array dengan menggunakan Arrays.equals () untuk membandingkan dua tatasusunan:

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()))); }

Tidak seperti Map.equals () , kaedah kita sendiri akan berjaya membandingkan HashMaps dengan nilai array:

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

4. Membandingkan Kekunci dan Nilai HashMap

Seterusnya, mari kita lihat bagaimana membandingkan dua kekunci HashMap dan nilai yang sepadan.

4.1. Membandingkan Kekunci HashMap

Pertama, kita dapat memeriksa sama ada dua HashMaps mempunyai kunci yang sama dengan hanya membandingkan KeySet mereka () :

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

4.2. Membandingkan Nilai HashMap

Seterusnya, kita akan melihat bagaimana membandingkan nilai HashMap satu persatu.

Kami akan menerapkan kaedah mudah untuk memeriksa kunci mana yang mempunyai nilai yang sama di kedua HashMaps menggunakan Stream 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())))); }

Kita sekarang boleh menggunakan areEqualKeyValues ​​() untuk membandingkan dua HashMaps yang berbeza untuk melihat secara terperinci kunci mana yang mempunyai nilai yang sama dan yang mempunyai nilai yang berbeza:

@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. Perbezaan Peta Menggunakan Jambu Batu

Akhirnya, kita akan melihat bagaimana mendapatkan perbezaan terperinci antara dua HashMaps menggunakan Guava Maps.difference ().

Kaedah ini mengembalikan objek MapDifference yang mempunyai sejumlah kaedah berguna untuk menganalisis perbezaan antara Peta. Mari kita lihat beberapa perkara ini.

5.1. MapDifference.entriesDiffering ()

Pertama, kami akan memperoleh kunci biasa yang mempunyai nilai yang berbeza dalam setiap HashMap menggunakan 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()); }
    

Kaedah entriDiffering () mengembalikan Peta baru yang mengandungi sekumpulan kunci bersama dan objek ValueDifference sebagai kumpulan nilai.

Setiap objek ValueDifference mempunyai kaedah leftValue () dan rightValue () yang masing-masing mengembalikan nilai dalam dua Peta .

5.2. MapDifference.entriesOnlyOnRight () dan MapDifference.entriesOnlyOnLeft ()

Kemudian, kita boleh mendapatkan entri yang terdapat hanya dalam satu HashMap menggunakan MapDifference.entriesOnlyOnRight () dan 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 ()

Seterusnya, kami akan mendapat entri biasa menggunakan 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. Menyesuaikan Peta. Perbezaan () Kelakuan

Oleh kerana Maps.difference () menggunakan sama () dan hashCode () secara lalai untuk membandingkan entri, ia tidak akan berfungsi untuk Objek yang tidak melaksanakannya dengan betul:

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

Tetapi, kita dapat menyesuaikan kaedah yang digunakan dalam perbandingan menggunakan Equivalence .

Sebagai contoh, kami akan menentukan Kesetaraan untuk jenis String [] untuk membandingkan nilai String [] dalam HashMaps kami seperti yang kami mahukan:

@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. Kesimpulannya

Dalam artikel ini, kami membincangkan pelbagai cara untuk membandingkan HashMaps di Java. Kami belajar pelbagai cara untuk memeriksa sama ada dua HashMaps sama dan bagaimana mendapatkan perbezaan terperinci juga.

Kod sumber lengkap boleh didapati di GitHub.