Java 中的泛型 Map

更新于 2025-12-28

Jakob Jenkov 2015-09-02

Java 的 Map 接口(java.util.Map)可以被泛型化。换句话说,你可以为泛型 Map 实例指定键和值的具体类型。例如:

Map<Integer, String> map = new HashMap<Integer, String>();

这个 Map 现在只能接受 Integer 类型的键和 String 类型的值。

注意:泛型类型检查仅在编译时存在。在运行时,仍有可能通过某些手段将其他类型的对象插入其中,但这是非常不推荐的做法。

访问泛型 Map

向泛型 Map 中添加或获取元素,仍然使用你熟悉的 put()get() 方法:

Map<Integer, String> map = new HashMap<Integer, String>();

Integer key1 = new Integer(123);
String value1 = "value 1";

map.put(key1, value1);

String value1_1 = map.get(key1);

那么,泛型带来了什么不同呢?

  • 如果你尝试向上述 Map 中插入非 Integer 键或非 String 值,编译器会报错。这是一个非常有用的额外类型检查。
  • 注意,从 get() 方法返回的 String 对象不需要强制类型转换。因为编译器知道该 Map 的值类型是 String,所以自动进行了类型安全处理。

你还可以利用 Java 5 引入的**自动装箱(autoboxing)**特性,使代码更简洁:

Map<Integer, String> map = new HashMap<Integer, String>();

Integer key1 = 123; // 自动装箱
String value1 = "value 1";

map.put(key1, value1);
// 或者直接写成:
map.put(123, value1);

String value1_1 = map.get(123); // 自动拆箱

遍历泛型 Map

Map 提供了两个可遍历的集合:键的 Set值的 Collection。通常我们会遍历键集,并通过 Map.get() 方法获取对应的值。

以下是两个示例:

使用 Iterator 遍历

Map<Integer, String> map = new HashMap<Integer, String>();
// ... 向 Map 中添加键值对

// 遍历键
Iterator<Integer> keyIterator = map.keySet().iterator();
while (keyIterator.hasNext()) {
    Integer aKey = keyIterator.next();
    String aValue = map.get(aKey);
}

// 遍历值
Iterator<String> valueIterator = map.values().iterator();
while (valueIterator.hasNext()) {
    String aString = valueIterator.next();
}

注意:由于 Map 是泛型化的,编译器知道键是 Integer、值是 String,因此从 iterator.next() 返回的对象无需强制转换

使用增强 for 循环(for-each)

Map<Integer, String> map = new HashMap<Integer, String>();
// ... 添加键值对

// 遍历键
for (Integer aKey : map.keySet()) {
    String aValue = map.get(aKey);
    System.out.println("" + aKey + ":" + aValue);
}

// 遍历值
for (String aValue : map.values()) {
    System.out.println(aValue);
}

注意:在 for 循环的括号中声明了 IntegerString 类型的变量。每次迭代时,该变量都会自动持有当前元素(即当前的 Integer 键或 String 值)。