Skip to content

Map 核心方法:视图与批量操作

Map 的三类视图

Map 不像 List 那样直接存储元素,它存储的是「键值对」。访问这些键值对有三种方式:

Map 的三个视图

├── keySet()      → Set<K>        所有 key
├── values()      → Collection<V> 所有 value
└── entrySet()   → Set<Entry<K,V>> 所有键值对

重要:这三个返回的都是视图,不是副本。对视图的修改会影响原 Map。


keySet():所有 key

java
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);

// 获取所有 key
Set<String> keys = map.keySet();
System.out.println(keys); // [a, b, c]

// 通过 keySet 删除
keys.remove("a"); // map 中也会删除 a=1

// 通过 keySet 遍历
for (String key : map.keySet()) {
    System.out.println(key);
}

keySet 是可修改的视图

java
// keySet().remove(key) 会从原 Map 中删除
map.keySet().remove("b");
System.out.println(map); // {c=3}

// 但 keySet().add(key) 呢?
// ❌ UnsupportedOperationException
// map.keySet().add("d"); // 不支持,因为 Map 没有 add 方法

values():所有 value

java
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);

// 获取所有 value
Collection<Integer> values = map.values();
System.out.println(values); // [1, 2, 3]

// values().remove(value) 会从原 Map 中删除
values.remove(2); // 删除 b=2
System.out.println(map); // {a=1, c=3}

entrySet():所有键值对

entrySet 是最有用的视图,因为可以同时获取 key 和 value:

java
Map<String, Integer> map = new HashMap<>();
map.put("apple", 3);
map.put("banana", 1);
map.put("cherry", 2);

// 遍历 entrySet
for (Map.Entry<String, Integer> entry : map.entrySet()) {
    System.out.println(entry.getKey() + " = " + entry.getValue());
}

// 修改 entry 的 value
for (Map.Entry<String, Integer> entry : map.entrySet()) {
    if (entry.getValue() > 1) {
        entry.setValue(entry.getValue() * 2);
    }
}
// {apple=6, banana=1, cherry=4}

Map.Entry 接口

每个 entry 都是一个 Map.Entry<K, V> 对象:

java
public interface Map.Entry<K, V> {
    K getKey();       // 获取 key
    V getValue();     // 获取 value
    V setValue(V);    // 设置 value(可变 Map 支持)
    // 比较、哈希等方法...
}

创建 Entry

java
// JDK 9+:Map.entry() 便捷方法
Map.Entry<String, Integer> entry = Map.entry("apple", 3);
System.out.println(entry.getKey());   // apple
System.out.println(entry.getValue()); // 3

按 key 或 value 排序 entry

java
Map<String, Integer> map = new HashMap<>();
map.put("apple", 3);
map.put("banana", 1);
map.put("cherry", 2);

// 按 key 排序
List<Map.Entry<String, Integer>> byKey = new ArrayList<>(map.entrySet());
Collections.sort(byKey, Map.Entry.comparingByKey());
System.out.println(byKey); // [apple, banana, cherry]

// 按 value 排序
List<Map.Entry<String, Integer>> byValue = new ArrayList<>(map.entrySet());
Collections.sort(byValue, Map.Entry.comparingByValue());
System.out.println(byValue); // [banana, cherry, apple]

批量操作

putAll():合并另一个 Map

java
Map<String, Integer> map1 = new HashMap<>();
map1.put("a", 1);
map1.put("b", 2);

Map<String, Integer> map2 = new HashMap<>();
map2.put("b", 20); // 覆盖
map2.put("c", 30);

map1.putAll(map2);
System.out.println(map1); // {a=1, b=20, c=30}

keySet.removeIf():批量删除

JDK 8+ 的 removeIf 可以批量删除满足条件的元素:

java
Map<String, Integer> map = new HashMap<>();
map.put("apple", 3);
map.put("banana", 1);
map.put("cherry", 2);
map.put("date", 4);

// 删除 value > 2 的条目
map.entrySet().removeIf(e -> e.getValue() > 2);
System.out.println(map); // {banana=1, cherry=2}

clear():清空 Map

java
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.clear();
System.out.println(map); // {}

子视图:subMap / headMap / tailMap

这是 TreeMap(和 SortedMap)独有的功能:

java
TreeMap<Integer, String> map = new TreeMap<>();
map.put(1, "one");
map.put(5, "five");
map.put(10, "ten");
map.put(15, "fifteen");
map.put(20, "twenty");

// subMap:区间视图(左闭右开)
SortedMap<Integer, String> sub = map.subMap(5, 15);
System.out.println(sub); // {5=five, 10=ten}

// headMap:头部视图(< key)
SortedMap<Integer, String> head = map.headMap(10);
System.out.println(head); // {1=one, 5=five}

// tailMap:尾部视图(>= key)
SortedMap<Integer, String> tail = map.tailMap(15);
System.out.println(tail); // {15=fifteen, 20=twenty}

// NavigableMap 提供更精细的控制
NavigableMap<Integer, String> nav = map.subMap(1, true, 20, false);
System.out.println(nav); // {1=one, 5=five, 10=ten, 15=fifteen}

注意:HashMap 不支持这些操作。


视图与原 Map 的关系

java
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);

// 视图会反映原 Map 的变化
map.put("c", 3);
System.out.println(map.keySet()); // [a, b, c]

// 反过来,修改视图也会影响原 Map
map.keySet().remove("a");
System.out.println(map); // {b=2, c=3}

// 通过 values().clear() 清空整个 Map
map.values().clear();
System.out.println(map); // {}

不可变视图

Collections.unmodifiableXxx() 可以创建只读视图:

java
Map<String, Integer> original = new HashMap<>();
original.put("a", 1);

// 不可变包装
Map<String, Integer> readOnly = Collections.unmodifiableMap(original);
readOnly.put("b", 2); // UnsupportedOperationException

// 但修改原 Map 会影响不可变视图
original.put("c", 3);
System.out.println(readOnly); // {a=1, c=3}

方法总结

视图/批量方法说明适用范围
keySet()返回所有 key所有 Map
values()返回所有 value所有 Map
entrySet()返回所有键值对所有 Map
putAll(map)合并另一个 Map所有 Map
clear()清空所有元素所有 Map
entrySet().removeIf()批量删除JDK 8+
subMap(head/tail)子区间视图SortedMap/TreeMap
Collections.unmodifiableXxx()只读视图所有 Map

总结

要点说明
视图特性keySet/values/entrySet 的修改影响原 Map
遍历推荐for (Map.Entry<K,V> e : map.entrySet())
批量删除entrySet().removeIf(predicate)
不可变包装Collections.unmodifiableMap()
子视图只有 SortedMap/TreeMap 支持

一句话:Map 的视图是原 Map 的「窗户」——看得见、摸得着(也会影响原 Map)。


相关链接

基于 VitePress 构建