深入学习HashMap、LinkedHashMap和TreeMap的特性与应用
Map接口是Java集合框架中的重要组成部分,它表示键值对(key-value)的映射关系。Map中的每个元素都包含一个唯一的键和对应的值,通过键可以快速查找到对应的值。
// 基本操作
V put(K key, V value) // 添加键值对
V get(Object key) // 根据键获取值
V remove(Object key) // 删除键值对
boolean containsKey(Object key) // 检查是否包含指定键
boolean containsValue(Object value) // 检查是否包含指定值
int size() // 获取元素个数
boolean isEmpty() // 检查是否为空
void clear() // 清空所有元素
// 批量操作
void putAll(Map extends K, ? extends V> m) // 添加另一个Map的所有元素
// 视图操作
Set keySet() // 获取所有键的Set视图
Collection values() // 获取所有值的Collection视图
Set> entrySet() // 获取所有键值对的Set视图
HashMap是最常用的Map实现,基于哈希表数据结构,提供了快速的插入、删除和查找操作。
import java.util.*;
public class HashMapExample {
public static void main(String[] args) {
// 创建HashMap
Map<String, Integer> map = new HashMap<>();
// 添加元素
map.put("apple", 5);
map.put("banana", 3);
map.put("orange", 8);
map.put("grape", 12);
// 获取元素
System.out.println("苹果数量: " + map.get("apple"));
// 检查键是否存在
if (map.containsKey("banana")) {
System.out.println("有香蕉库存");
}
// 遍历Map
System.out.println("\n所有水果库存:");
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// 使用forEach遍历(Java 8+)
System.out.println("\n使用forEach遍历:");
map.forEach((fruit, count) ->
System.out.println(fruit + " => " + count)
);
// 更新值
map.put("apple", map.get("apple") + 2); // 增加苹果数量
// 使用merge方法更新
map.merge("banana", 5, Integer::sum); // 如果键存在则相加,否则设置新值
System.out.println("\n更新后的苹果数量: " + map.get("apple"));
System.out.println("更新后的香蕉数量: " + map.get("banana"));
}
}
LinkedHashMap继承自HashMap,额外维护了一个双向链表来保持元素的插入顺序或访问顺序。
import java.util.*;
public class LinkedHashMapExample {
public static void main(String[] args) {
// 创建保持插入顺序的LinkedHashMap
Map<String, String> insertionOrder = new LinkedHashMap<>();
insertionOrder.put("first", "第一个");
insertionOrder.put("second", "第二个");
insertionOrder.put("third", "第三个");
System.out.println("插入顺序遍历:");
insertionOrder.forEach((k, v) -> System.out.println(k + " = " + v));
// 创建按访问顺序排列的LinkedHashMap
Map<String, String> accessOrder = new LinkedHashMap<>(16, 0.75f, true);
accessOrder.put("A", "值A");
accessOrder.put("B", "值B");
accessOrder.put("C", "值C");
// 访问元素A,它会移到最后
accessOrder.get("A");
System.out.println("\n访问顺序遍历(访问A后):");
accessOrder.forEach((k, v) -> System.out.println(k + " = " + v));
}
}
TreeMap基于红黑树实现,能够自动对键进行排序,并提供了丰富的导航方法。
import java.util.*;
public class TreeMapExample {
public static void main(String[] args) {
// 创建TreeMap,自动按键排序
TreeMap<Integer, String> treeMap = new TreeMap<>();
treeMap.put(3, "三");
treeMap.put(1, "一");
treeMap.put(4, "四");
treeMap.put(2, "二");
treeMap.put(5, "五");
System.out.println("自动排序后的遍历:");
treeMap.forEach((k, v) -> System.out.println(k + " = " + v));
// 导航方法
System.out.println("\n导航方法演示:");
System.out.println("第一个键: " + treeMap.firstKey());
System.out.println("最后一个键: " + treeMap.lastKey());
System.out.println("小于3的最大键: " + treeMap.lowerKey(3));
System.out.println("大于3的最小键: " + treeMap.higherKey(3));
// 子映射
System.out.println("\n子映射(键在2到4之间):");
SortedMap<Integer, String> subMap = treeMap.subMap(2, 5);
subMap.forEach((k, v) -> System.out.println(k + " = " + v));
// 自定义比较器
TreeMap<String, Integer> customOrder = new TreeMap<>(
(s1, s2) -> s2.compareTo(s1) // 逆序排列
);
customOrder.put("apple", 5);
customOrder.put("banana", 3);
customOrder.put("cherry", 8);
System.out.println("\n自定义逆序排列:");
customOrder.forEach((k, v) -> System.out.println(k + " = " + v));
}
}
操作 | HashMap | LinkedHashMap | TreeMap |
---|---|---|---|
插入(put) | O(1) | O(1) | O(log n) |
查找(get) | O(1) | O(1) | O(log n) |
删除(remove) | O(1) | O(1) | O(log n) |
遍历 | O(n) | O(n) | O(n) |
空间复杂度 | O(n) | O(n) + 链表开销 | O(n) + 树结构开销 |
Map<K,V> map = new HashMap<>();
import java.util.*;
public class MapApplications {
// 1. 缓存实现(使用LinkedHashMap)
public static class LRUCache<K, V> extends LinkedHashMap<K, V> {
private final int capacity;
public LRUCache(int capacity) {
super(capacity, 0.75f, true);
this.capacity = capacity;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > capacity;
}
}
// 2. 统计词频(使用HashMap)
public static Map<String, Integer> countWords(String text) {
Map<String, Integer> wordCount = new HashMap<>();
String[] words = text.toLowerCase().split("\\s+");
for (String word : words) {
wordCount.merge(word, 1, Integer::sum);
}
return wordCount;
}
// 3. 配置管理(使用TreeMap保持有序)
public static class ConfigManager {
private TreeMap<String, String> configs = new TreeMap<>();
public void setConfig(String key, String value) {
configs.put(key, value);
}
public String getConfig(String key) {
return configs.get(key);
}
public void printAllConfigs() {
configs.forEach((k, v) ->
System.out.println(k + " = " + v)
);
}
}
public static void main(String[] args) {
// 测试LRU缓存
LRUCache<String, String> cache = new LRUCache<>(3);
cache.put("1", "one");
cache.put("2", "two");
cache.put("3", "three");
cache.put("4", "four"); // 会移除最久未使用的"1"
System.out.println("LRU缓存内容: " + cache);
// 测试词频统计
String text = "hello world hello java world";
Map<String, Integer> wordCount = countWords(text);
System.out.println("\n词频统计: " + wordCount);
// 测试配置管理
ConfigManager config = new ConfigManager();
config.setConfig("database.url", "jdbc:mysql://localhost:3306/test");
config.setConfig("app.name", "MyApp");
config.setConfig("cache.size", "1000");
System.out.println("\n配置信息:");
config.printAllConfigs();
}
}