概述
本教程将探讨如何在Java中处理嵌套的HashMap
。我们将学习如何创建、比较它们,以及如何向内层地图添加和删除记录。
嵌套HashMap
的应用场景
嵌套HashMap
非常适合存储JSON或类似JSON的结构,其中对象嵌套在其他对象中。例如,类似以下结构的JSON:
{
"d5a46b57-7cb1-441a-a743-b6507a6b3a5c": {
// 其他嵌套数据
}
}
在这种情况下,嵌套HashMap
是理想的选择。一般来说,当我们需要在一个对象中嵌套另一个对象时,都可以使用它们。
创建HashMap
创建HashMap
的方法有很多种,比如手动构造、使用流(Streams)和分组函数等。HashMap
可以包含基本类型或对象。
3.1 使用put()
方法
我们可以通过手动创建内层地图,然后使用put
方法插入到外层地图中来构建嵌套HashMap
:
Map<String, Map<String, String>> nestedMap = new HashMap<>();
nestedMap.put("key1", new HashMap<>());
nestedMap.get("key1").put("innerKey", "innerValue");
我们可以用以下代码进行测试:
nestedMap.get("key1").get("innerKey"); // 返回 "innerValue"
3.2 使用流(Streams)
如果我们有一个想要转换为Map
的List
,我们可以创建一个流,然后使用Collectors.toMap
方法将其转换为Map
。这里有两个例子:一个是包含字符串内层Map
的,另一个是具有整数和对象值的Map
。
第一个例子中,Employee
对象内嵌有Address
对象,我们构建了一个嵌套HashMap
:
List<Employee> employees = ...;
Map<String, Employee> employeeMap = employees.stream()
.collect(Collectors.toMap(Employee::getId, e -> new HashMap<>(e.getAddress().entrySet())));
第二个例子中,我们构建了一个<Employee id, Address id, Address object>
类型的对象:
Map<Integer, Map<Integer, Address>> addressMap = ...;
遍历嵌套HashMap
遍历嵌套HashMap
与遍历普通或非嵌套的HashMap
没有区别。嵌套Map
与普通Map
的主要区别在于嵌套HashMap
的值是Map
类型:
for (Map.Entry<String, Map<String, String>> entry : nestedMap.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
比较嵌套HashMap
在Java中,有许多方法可以比较HashMap
。我们可以使用equals()
方法进行比较。默认实现会逐个比较值。
如果改变内层地图的内容,平等检查会失败。对于用户自定义对象,如果每次内层对象都是新实例,那么平等检查也会失败。同样,如果改变外层Map
的内容,平等检查也将失败:
nestedMap1.equals(nestedMap2); // 返回 false
对于值为用户自定义对象的Map
,我们需要使用比较HashMap
文章中提到的一种方法自定义相等性方法,否则检查将失败:
nestedMap1.equalsUsingCustomComparator(nestedMap2); // 自定义比较逻辑
如果两个地图相同,那么平等检查将成功。对于用户自定义地图,如果所有相同的对象都被移动到另一个地图中,平等检查也将成功:
nestedMap1.equalsUsingCustomComparator(sameObjectsMap); // 返回 true
向嵌套HashMap
添加元素
要向嵌套HashMap
的内层Map
添加元素,首先需要获取它。我们可以使用get()
方法获取内层对象,然后对内层Map
对象使用put()
方法插入新值:
Map<String, Map<String, String>> nestedMap = ...;
nestedMap.get("outerKey").put("innerKey", "newValue");
如果要向外层Map
添加条目,还需要提供正确的内层Map
条目:
Map<String, Map<String, String>> outerMap = ...;
outerMap.put("outerKey", new HashMap<>());
outerMap.get("outerKey").put("innerKey", "innerValue");
从嵌套HashMap
删除记录
要从内层Map
中删除记录,首先需要获取它,然后使用remove()
方法删除。如果内层Map
中只有一个值,那么删除后将留下一个null
对象作为值:
Map<String, Map<String, String>> nestedMap = ...;
nestedMap.get("outerKey").remove("innerKey"); // 如果只有一个值,将变为 null
nestedMap.get("outerKey").isEmpty(); // 如果内层为空,返回 true
如果从外层Map
中删除记录,Java会同时删除内外层的记录,因为内层Map
是外层Map
的“值”:
nestedMap.remove("outerKey"); // 外层和内层都会被删除
展平嵌套HashMap
嵌套HashMap
的替代方案是使用组合键。组合键通常将嵌套结构的两个键以点分隔。例如,组合键可能是Donut.1
、Donut.2
等。我们可以将嵌套的Map
结构转换为单一Map
结构,即“展平”:
Map<String, String> flattenedMap = new HashMap<>();
flattenedMap.put("Donut.1", "value1");
flattenedMap.put("Donut.2", "value2");
组合键方法克服了嵌套HashMap
带来的额外内存存储劣势。然而,组合键方法在扩展性方面并不理想。
结论
在这篇文章中,我们了解了如何创建、比较、更新和展平嵌套HashMap
。如往常一样,代码可以在GitHub上找到。