Java Map 集合
Map 是 Java 集合框架中用于存储键值对的接口。理解 Map 的实现类和使用方法是处理映射关系的基础。本章将详细介绍 Java 中的 Map 集合。
Java Map 集合类型
HashMap、LinkedHashMap、TreeMap 是 Java 的三大 Map 集合类型,下面逐一介绍。
HashMap
HashMap 是基于哈希表实现的,使用数组+链表+红黑树(Java 8+)结构。
特点:
- 无序:键值对没有固定顺序
- 键唯一:每个 key 只能对应一个 value
- 查找快:平均时间复杂度 O(1)
- 允许 null:key 和 value 都可以为 null(但只能有一个 null key)
- 线程不安全:多线程环境下需要同步
import java.util.HashMap;
import java.util.Map;
Map<String, Integer> map = new HashMap<>();
map.put("apple", 10);
map.put("banana", 20);
map.put("orange", 30);
System.out.println(map); // {banana=20, orange=30, apple=10}(顺序不确定)
System.out.println(map.get("apple")); // 10
LinkedHashMap
LinkedHashMap 是 HashMap 的子类,使用链表维护插入顺序。
特点:
- 有序:保持插入顺序
- 键唯一:每个 key 只能对应一个 value
- 查找快:平均时间复杂度 O(1)
- 性能略低:比 HashMap 略慢(需要维护链表)
import java.util.LinkedHashMap;
Map<String, Integer> map = new LinkedHashMap<>();
map.put("apple", 10);
map.put("banana", 20);
map.put("orange", 30);
System.out.println(map); // {apple=10, banana=20, orange=30}(保持插入顺序)
TreeMap
TreeMap 是基于红黑树实现的,按键的自然顺序或指定比较器排序。
特点:
- 有序:按键自动排序
- 键唯一:每个 key 只能对应一个 value
- 查找较慢:时间复杂度 O(log n)
- 支持范围查询:可以高效查询范围内的键
import java.util.TreeMap;
Map<String, Integer> map = new TreeMap<>();
map.put("orange", 30);
map.put("apple", 10);
map.put("banana", 20);
System.out.println(map); // {apple=10, banana=20, orange=30}(按键排序)
key-value 操作
添加和更新
Map<String, Integer> map = new HashMap<>();
// 添加键值对
map.put("apple", 10); // 添加新键值对
map.put("banana", 20); // 添加新键值对
map.put("apple", 30); // 更新已存在的键的值
// 如果不存在则添加
map.putIfAbsent("orange", 40); // 如果 "orange" 不存在,则添加
// 批量添加
Map<String, Integer> anotherMap = new HashMap<>();
anotherMap.put("grape", 50);
anotherMap.put("mango", 60);
map.putAll(anotherMap);
获取值
Map<String, Integer> map = new HashMap<>();
map.put("apple", 10);
map.put("banana", 20);
// 获取值
Integer value = map.get("apple"); // 10
// 获取值,如果不存在返回默认值
Integer value2 = map.getOrDefault("orange", 0); // 0(不存在,返回默认值)
// 检查键是否存在
boolean containsKey = map.containsKey("apple"); // true
// 检查值是否存在
boolean containsValue = map.containsValue(10); // true
删除
Map<String, Integer> map = new HashMap<>();
map.put("apple", 10);
map.put("banana", 20);
map.put("orange", 30);
// 按键删除
Integer removed = map.remove("apple"); // 返回删除的值:10
// 按键值对删除(只有键和值都匹配才删除)
boolean removed2 = map.remove("banana", 25); // false(值不匹配)
boolean removed3 = map.remove("banana", 20); // true(键值都匹配)
// 清空
map.clear(); // 删除所有键值对
替换
Map<String, Integer> map = new HashMap<>();
map.put("apple", 10);
map.put("banana", 20);
// 替换值
map.replace("apple", 15); // 替换为 15
// 只有旧值匹配才替换
boolean replaced = map.replace("banana", 20, 25); // true(旧值是 20,替换为 25)
// 替换所有值
map.replaceAll((key, value) -> value * 2); // 所有值乘以 2
遍历 Map 方法
方法 1:遍历键
Map<String, Integer> map = new HashMap<>();
map.put("apple", 10);
map.put("banana", 20);
// 遍历所有键
for (String key : map.keySet()) {
System.out.println(key + " = " + map.get(key));
}
// 使用迭代器
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
System.out.println(key + " = " + map.get(key));
}
方法 2:遍历值
// 遍历所有值
for (Integer value : map.values()) {
System.out.println(value);
}
方法 3:遍历键值对(推荐)
// 遍历所有键值对
for (Map.Entry<String, Integer> entry : map.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + " = " + value);
}
// 使用迭代器
Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Integer> entry = iterator.next();
System.out.println(entry.getKey() + " = " + entry.getValue());
}
方法 4:Lambda 表达式(Java 8+)
// 遍历键值对
map.forEach((key, value) -> {
System.out.println(key + " = " + value);
});
// 或使用方法引用
map.forEach((key, value) -> System.out.println(key + " = " + value));
方法 5:Stream API(Java 8+)
// 过滤和遍历
map.entrySet().stream()
.filter(entry -> entry.getValue() > 15)
.forEach(entry -> System.out.println(entry.getKey() + " = " + entry.getValue()));
示例:统计词频、计数器实现
示例 1:统计词频
import java.util.*;
public class WordFrequency {
public static Map<String, Integer> countWords(String text) {
Map<String, Integer> frequency = new HashMap<>();
// 分割单词
String[] words = text.toLowerCase().split("\\s+");
// 统计词频
for (String word : words) {
frequency.put(word, frequency.getOrDefault(word, 0) + 1);
}
return frequency;
}
public static void main(String[] args) {
String text = "apple banana apple orange banana apple";
Map<String, Integer> frequency = countWords(text);
// 按频率排序
frequency.entrySet().stream()
.sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
.forEach(entry -> System.out.println(entry.getKey() + ": " + entry.getValue()));
}
}
示例 2:计数器实现
import java.util.*;
public class Counter {
private Map<String, Integer> counts = new HashMap<>();
public void increment(String key) {
counts.put(key, counts.getOrDefault(key, 0) + 1);
}
public void decrement(String key) {
counts.put(key, Math.max(0, counts.getOrDefault(key, 0) - 1));
}
public int getCount(String key) {
return counts.getOrDefault(key, 0);
}
public void reset(String key) {
counts.remove(key);
}
public void resetAll() {
counts.clear();
}
public Map<String, Integer> getAllCounts() {
return new HashMap<>(counts);
}
public static void main(String[] args) {
Counter counter = new Counter();
counter.increment("apple");
counter.increment("apple");
counter.increment("banana");
System.out.println("apple 计数:" + counter.getCount("apple")); // 2
System.out.println("banana 计数:" + counter.getCount("banana")); // 1
}
}