Java >> Java tutorial >  >> Tag >> HashMap

Indlejrede HashMaps-eksempler i Java

1. Oversigt

I denne selvstudie vil vi se på, hvordan man håndterer indlejrede HashMaps i Java. Vi vil også se, hvordan du opretter og sammenligner dem. Endelig vil vi også se, hvordan du fjerner og tilføjer poster til de indre kort.

2. Use Cases

Indlejret HashMap er meget nyttig til at gemme JSON eller JSON-lignende strukturer, hvor objekter er indlejret i hinanden. For eksempel en struktur eller JSON, der ligner:

{
    "type": "donut",
    "batters":
    {
        “batter”:
        [
            { "id": "1001", "type": "Regular" },
            { "id": "1002", "type": "Chocolate" },
            { "id": "1003", "type": "Blueberry" },
            { "id": "1004", "type": "Devil's Food" }
        ]
    }
} 

er en perfekt kandidat til et indlejret HashMap . Generelt, når vi har brug for at indlejre et objekt i et andet objekt, kan vi bruge dem.

3. Opret et HashMap

Der er flere måder at oprette et HashMap på , såsom manuelt at konstruere kortene eller bruge Streams og grupperingsfunktioner. Kort struktur kan være både med primitive typer såvel som Objekter .

3.1. Ved at bruge p ut() Metode

Vi kan bygge et indlejret HashMap ved manuelt at oprette de indre kort og derefter indsætte dem i det ydre Kort ved hjælp af put-metoden:

public Map<Integer, String> buildInnerMap(List<String> batterList) {
     Map<Integer, String> innerBatterMap = new HashMap<Integer, String>();
     int index = 1;
     for (String item : batterList) {
         innerBatterMap.put(index, item);
         index++;
     }
     return innerBatterMap;
}

Vi kan teste det med:

assertThat(mUtil.buildInnerMap(batterList), is(notNullValue()));
Assert.assertEquals(actualBakedGoodsMap.keySet().size(), 2);
Assert.assertThat(actualBakedGoodsMap, IsMapContaining.hasValue(equalTo(mUtil.buildInnerMap(batterList))));

3.2. Brug af streams

Hvis vi har en liste som vi ønsker at konvertere til et Kort , kan vi oprette en strøm og derefter konvertere den til et Kort ved hjælp af Collectors.toMap metode. Her har vi to eksempler:det ene har et indre Kort af strenge , og den anden er et Kort med Heltal og Objekt værdier.

I det første eksempel, Medarbejder har adressen objekt indlejret inde i det. Vi bygger derefter et indlejret HashMap :

Map<Integer, Map<String, String>> employeeAddressMap = listEmployee.stream()
  .collect(Collectors.groupingBy(e -> e.getAddress().getAddressId(),
    Collectors.toMap(f -> f.getAddress().getAddressLocation(), Employee::getEmployeeName)));
return employeeAddressMap;

I det andet eksempel bygger vi et objekt af typen > :

Map<Integer, Map<Integer, Address>> employeeMap = new HashMap<>();
employeeMap = listEmployee.stream().collect(Collectors.groupingBy((Employee emp) -> emp.getEmployeeId(),
  Collectors.toMap((Employee emp) -> emp.getAddress().getAddressId(), fEmpObj -> fEmpObj.getAddress())));
return employeeMap;

4. Iteration gennem et indlejret HashMap

Iteration gennem et indlejret hashmap er ikke anderledes end at gentage et almindeligt eller ikke-indlejret HashMap . Den eneste forskel mellem et indlejret og almindeligt kort er, at værdierne af et indlejret HashMap er Kort  type:

for (Map.Entry<String, Map<Integer, String>> outerBakedGoodsMapEntrySet : outerBakedGoodsMap.entrySet()) {
    Map<Integer, String> valueMap = outerBakedGoodsMapEntrySet.getValue();
    System.out.println(valueMap.entrySet());
}

for (Map.Entry<Integer, Map<String, String>> employeeEntrySet : employeeAddressMap.entrySet()) {
    Map<String, String> valueMap = employeeEntrySet.getValue();
    System.out.println(valueMap.entrySet());
}

5. Sammenligning af indlejrede HashMap s

Der er mange måder at sammenligne HashMap på s i Java. Vi kan sammenligne dem ved at bruge equals() metode. Standardimplementeringen sammenligner hver værdi.

Hvis vi ændrer det indre Maps indhold, mislykkes lighedskontrollen. Hvis de indre objekter alle er nye instanser hver gang i tilfælde af brugerdefinerede objekter, vil lighedskontrollen også mislykkes. På samme måde, hvis vi ændrer det ydre Kort 's indhold, vil ligestillingskontrollen også mislykkes:

assertNotEquals(outerBakedGoodsMap2, actualBakedGoodsMap);

outerBakedGoodsMap3.put("Donut", mUtil.buildInnerMap(batterList));
assertNotEquals(outerBakedGoodsMap2, actualBakedGoodsMap);

Map<Integer, Map<String, String>> employeeAddressMap1 = mUtil.createNestedMapfromStream(listEmployee);
assertNotEquals(employeeAddressMap1, actualEmployeeAddressMap);

Til kortet med brugerdefinerede objekter som værdier, skal vi tilpasse lighedsmetoden ved hjælp af en af ​​metoderne nævnt i det sammenlignende HashMap s artikel. Ellers vil kontrollerne mislykkes:

//Comparing a Map<Integer, Map<String, String>> and Map<Integer, Map<Integer, Address>> map
assertNotSame(employeeMap1, actualEmployeeMap);
assertNotEquals(employeeMap1, actualEmployeeMap);
Map<Integer, Map<Integer, Address>> expectedMap = setupAddressObjectMap();
assertNotSame(expectedMap, actualEmployeeMap);
assertNotEquals(expectedMap, actualEmployeeMap);

Hvis begge kort er ens, så lykkes lighedskontrollen. For et brugerdefineret kort, hvis alle identiske objekter flyttes til et andet kort, lykkes lighedskontrollen:

Map<String, Map<Integer, String>> outerBakedGoodsMap4 = new HashMap<>();
outerBakedGoodsMap4.putAll(actualBakedGoodsMap);
assertEquals(actualBakedGoodsMap, outerBakedGoodsMap4);
Map<Integer, Map<Integer, Address>> employeeMap1 = new HashMap<>();
employeeMap1.putAll(actualEmployeeMap);
assertEquals(actualEmployeeMap, employeeMap1);

6. Tilføjelse af elementer til Nested HashMap s

For at tilføje et element til det indre Kort af det indlejrede HashMap , vi skal først hente det. Vi kan hente det indre objekt ved hjælp af get() metode. Så kan vi bruge put() metode på det indre Kort objekt og indsæt de nye værdier:

assertEquals(actualBakedGoodsMap.get("Cake").size(), 5);
actualBakedGoodsMap.get("Cake").put(6, "Cranberry");
assertEquals(actualBakedGoodsMap.get("Cake").size(), 6);

Hvis vi skal tilføje en post til det ydre Kort , skal vi levere de korrekte indtastninger til det indre Kort s også:

outerBakedGoodsMap.put("Eclair", new HashMap<Integer, String>() {
    {
        put(1, "Dark Chocolate");
    }
});

7. Sletning af poster fra indlejrede HashMap s

For at slette posten fra det indre Kort , først skal vi hente det og derefter bruge remove() metode til at slette det. Hvis der kun er én værdi i det indre Kort , derefter en null objekt efterlades som værdien:

assertNotEquals(actualBakedGoodsMap.get("Cake").get(5), null);
actualBakedGoodsMap.get("Cake").remove(5);
assertEquals(actualBakedGoodsMap.get("Cake").get(5), null);
assertNotEquals(actualBakedGoodsMap.get("Eclair").get(1), null);
actualBakedGoodsMap.get("Eclair").remove(1);
assertEquals(actualBakedGoodsMap.get("Eclair").get(1), null);
actualBakedGoodsMap.put("Eclair", new HashMap<Integer, String>() {
    {
        put(1, "Dark Chocolate");
    }
});

Hvis vi fjerner en post fra det ydre Kort , Java sletter både det indre og ydre Kort poster, hvilket er tydeligt siden det indre Kort er "værdien" af det ydre Kort :

assertNotEquals(actualBakedGoodsMap.get("Eclair"), null);
actualBakedGoodsMap.remove("Eclair");
assertEquals(actualBakedGoodsMap.get("Eclair"), null);

8. Flad et indlejret HashMap sammen

Et alternativ til et indlejret HashMap er at bruge kombinerede nøgler. En kombineret nøgle sammenkæder normalt de to nøgler fra den indlejrede struktur med en prik imellem. For eksempel ville den kombinerede nøgle være Donut.1 , Donut.2 , og så videre. Vi kan "flade", dvs. konvertere fra indlejret Kort struktur til et enkelt kort struktur:

var flattenedBakedGoodsMap = mUtil.flattenMap(actualBakedGoodsMap);
assertThat(flattenedBakedGoodsMap, IsMapContaining.hasKey("Donut.2"));
var flattenedEmployeeAddressMap = mUtil.flattenMap(actualEmployeeAddressMap);
assertThat(flattenedEmployeeAddressMap, IsMapContaining.hasKey("200.Bag End"));

Den kombinerede nøgletilgang overvinder ulemperne ved ekstra hukommelseslagring, der følger med indlejrede HashMaps . Men den kombinerede nøgletilgang er ikke særlig god til at skalere.

9. Konklusion

I denne artikel så vi, hvordan man opretter, sammenligner, opdaterer og udjævner et indlejret HashMap .

Som altid er koden tilgængelig på GitHub.


Java tag