1. 概要

このチュートリアルでは、JavaでネストされたHashMapsを処理する方法を見ていきます。 また、それらを作成して比較する方法についても説明します。 最後に、レコードを削除して内部マップに追加する方法についても説明します。

2. ユースケース

ネストされたHashMapは、オブジェクトが相互に埋め込まれているJSONまたはJSONのような構造を格納するのに非常に役立ちます。 たとえば、次のような構造またはJSON:

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

ネストされたHashMapの完璧な候補です。 一般に、あるオブジェクトを別のオブジェクトに埋め込む必要があるときはいつでも、それらを使用できます。

3. HashMapを作成します

HashMap を作成するには、手動でマップを作成したり、 Streams を使用して関数をグループ化したりするなど、複数の方法があります。 Map 構造は、プリミティブ型とObjectsの両方を使用できます。

3.1. p ut()メソッドの使用

ネストされたHashMapを構築するには、内側のマップを手動で作成し、putメソッドを使用してそれらを外側のMapに挿入します。

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

次の方法でテストできます。

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

3.2. ストリームの使用

マップに変換するリストがある場合は、ストリームを作成し、コレクターを使用してマップに変換できます。 .toMapメソッド。 ここでは、2つの例があります。1つはStringsの内部Mapで、もう1つはIntegerを持つMapです。 ]Object値。

最初の例では、Employeeの中にAddressオブジェクトがネストされています。 次に、ネストされた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;

2番目の例では、タイプのオブジェクトを作成しています >>

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. ネストされたHashMapを反復処理します

ネストされたHashmapを反復処理することは、通常のまたはネストされていないHashMapを反復処理することと同じです。 ネストされたMapと通常のMapの唯一の違いは、ネストされたHashMapの値がMapタイプであるということです。

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. ネストされたHashMapの比較

JavaでHashMapを比較する方法はたくさんあります。 equals()メソッドを使用してそれらを比較できます。 デフォルトの実装では、各値が比較されます。

内部マップの内容を変更すると、同等性チェックは失敗します。 ユーザー定義オブジェクトの場合、内部オブジェクトが毎回すべて新しいインスタンスである場合、同等性チェックも失敗します。 同様に、外側の Map の内容を変更すると、同等性チェックも失敗します。

assertNotEquals(outerBakedGoodsMap2, actualBakedGoodsMap);

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

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

ユーザー定義オブジェクトを値として持つMapの場合、 HashMapsの比較記事に記載されているメソッドの1つを使用して、等式メソッドをカスタマイズする必要があります。 そうしないと、チェックが失敗します。

//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);

両方のマップが同じである場合、同等性チェックは成功します。 ユーザー定義のマップの場合、すべての同一のオブジェクトが別のマップに移動されると、同等性チェックは成功します。

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. ネストされたHashMapへの要素の追加

ネストされたHashMapの内部Mapに要素を追加するには、最初にそれを取得する必要があります。 get()メソッドを使用して内部オブジェクトを取得できます。 次に、内側の Mapオブジェクトでput()メソッドを使用して、新しい値を挿入できます。

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

外側のMapにエントリを追加する必要がある場合は、内側のMapにも正しいエントリを指定する必要があります。

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

7. ネストされたハッシュマップからのレコードの削除

内部のMapからレコードを削除するには、まずレコードを取得してから、 remove()メソッドを使用してレコードを削除する必要があります。 内部のMapに値が1つしかない場合は、nullオブジェクトが値として残されます。

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

外側のMapからレコードを削除すると、Javaは内側と外側の Map レコードの両方を削除します。これは、内側のMapが「値」であることから明らかです。外側のマップの」:

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

8. ネストされたHashMapをフラット化する

ネストされたHashMapの代替手段の1つは、結合されたキーを使用することです。 結合されたキーは通常、ネストされた構造の2つのキーをドットで連結します。 たとえば、結合されたキーは Donut.1 Donut.2などになります。 「フラット化」できます。つまり、ネストされたMap構造から単一のMap構造に変換できます。

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

結合キーアプローチは、ネストされたHashMapsに伴う余分なメモリストレージの欠点を克服します。 ただし、キーを組み合わせたアプローチは、スケーリングがあまり得意ではありません。

9. 結論

この記事では、ネストされた HashMap を作成、比較、更新、およびフラット化する方法について説明しました。

いつものように、コードはGitHubから入手できます。