Java LinkedHashMap 实用案例
LinkedHashMap 基础特性
LinkedHashMap 继承自 HashMap,但保留了元素的插入顺序或访问顺序。

基本使用案例
1 保持插入顺序
import java.util.LinkedHashMap;
import java.util.Map;
public class InsertionOrderExample {
public static void main(String[] args) {
// 默认构造器:保持插入顺序
LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);
map.put("D", 4);
System.out.println("插入顺序遍历:");
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " -> " + entry.getValue());
}
// 输出:A -> 1, B -> 2, C -> 3, D -> 4
}
}
2 基于访问顺序的 LRU 缓存
import java.util.LinkedHashMap;
import java.util.Map;
public class AccessOrderExample {
public static void main(String[] args) {
// 第三个参数 true 表示按照访问顺序
LinkedHashMap<String, Integer> map = new LinkedHashMap<>(16, 0.75f, true);
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);
map.put("D", 4);
System.out.println("初始顺序:");
System.out.println(map); // {A=1, B=2, C=3, D=4}
// 访问元素
map.get("B");
map.get("D");
System.out.println("访问 B 和 D 后的顺序:");
System.out.println(map); // {A=1, C=3, B=2, D=4}
// 最近访问的 B 和 D 移到了末尾
}
}
实现 LRU 缓存(经典案例)
import java.util.LinkedHashMap;
import java.util.Map;
class LRUCache<K, V> extends LinkedHashMap<K, V> {
private final int maxSize;
public LRUCache(int maxSize) {
// 初始化容量,负载因子,访问顺序
super(maxSize, 0.75f, true);
this.maxSize = maxSize;
}
// 重写 removeEldestEntry 方法,当缓存满时移除最旧元素
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > maxSize;
}
}
public class LRUCacheExample {
public static void main(String[] args) {
LRUCache<Integer, String> cache = new LRUCache<>(3);
cache.put(1, "One");
cache.put(2, "Two");
cache.put(3, "Three");
System.out.println("初始缓存: " + cache);
// 输出:{1=One, 2=Two, 3=Three}
// 访问 key=1,使其成为最近使用
cache.get(1);
// 添加新元素,此时会移除最久未使用的元素(key=2)
cache.put(4, "Four");
System.out.println("添加 4 后: " + cache);
// 输出:{3=Three, 1=One, 4=Four}
// 再次访问 3
cache.get(3);
// 添加 5,移除 1(最久未使用)
cache.put(5, "Five");
System.out.println("添加 5 后: " + cache);
// 输出:{4=Four, 3=Three, 5=Five}
}
}
用户访问日志统计
import java.util.LinkedHashMap;
import java.util.Map;
public class UserAccessLogExample {
public static void main(String[] args) {
// 记录用户最近访问的页面,最多保存 5 条
recentPages();
// 记录用户访问频率
accessFrequency();
}
// 记录最近访问页面
public static void recentPages() {
LinkedHashMap<String, String> recentPages = new LinkedHashMap<>(5, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
return size() > 5;
}
};
// 模拟用户访问
recentPages.put("user1", "/home");
recentPages.put("user2", "/products");
recentPages.put("user1", "/cart");
recentPages.put("user3", "/checkout");
recentPages.put("user1", "/orders");
recentPages.put("user4", "/profile");
System.out.println("最近访问的用户界面:");
for (Map.Entry<String, String> entry : recentPages.entrySet()) {
System.out.println(entry.getKey() + " 最后访问: " + entry.getValue());
}
}
// 记录访问频率
public static void accessFrequency() {
// 保持插入顺序的记录
LinkedHashMap<String, Integer> accessCount = new LinkedHashMap<>();
String[] pages = {"/home", "/products", "/home", "/about",
"/home", "/products", "/contact", "/products"};
for (String page : pages) {
accessCount.merge(page, 1, Integer::sum);
}
System.out.println("\n页面访问统计(按首次访问顺序):");
for (Map.Entry<String, Integer> entry : accessCount.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue() + " 次");
}
}
}
自定义排序的配置系统
import java.util.LinkedHashMap;
import java.util.Map;
public class ConfigSystemExample {
public static void main(String[] args) {
// 保持配置项的添加顺序
LinkedHashMap<String, Object> systemConfig = new LinkedHashMap<>();
// 添加配置项(保持顺序很重要,比如数据库配置必须在应用配置之前)
addEssentialConfig(systemConfig);
addDatabaseConfig(systemConfig);
addApplicationConfig(systemConfig);
System.out.println("系统配置(按重要顺序):");
for (Map.Entry<String, Object> entry : systemConfig.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
private static void addEssentialConfig(LinkedHashMap<String, Object> config) {
config.put("server.port", 8080);
config.put("server.host", "localhost");
}
private static void addDatabaseConfig(LinkedHashMap<String, Object> config) {
config.put("db.url", "jdbc:mysql://localhost:3306/mydb");
config.put("db.username", "admin");
config.put("db.password", "secret");
}
private static void addApplicationConfig(LinkedHashMap<String, Object> config) {
config.put("app.name", "MyApp");
config.put("app.version", "1.0.0");
config.put("app.debug", true);
}
}
性能测试与对比
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class PerformanceComparison {
public static void main(String[] args) {
int size = 100000;
// 测试插入性能
long startTime = System.nanoTime();
LinkedHashMap<Integer, String> linkedMap = new LinkedHashMap<>();
for (int i = 0; i < size; i++) {
linkedMap.put(i, "Value" + i);
}
long linkedTime = System.nanoTime() - startTime;
startTime = System.nanoTime();
HashMap<Integer, String> hashMap = new HashMap<>();
for (int i = 0; i < size; i++) {
hashMap.put(i, "Value" + i);
}
long hashTime = System.nanoTime() - startTime;
System.out.println("插入 " + size + " 条数据:");
System.out.println("LinkedHashMap: " + linkedTime / 1_000_000 + " ms");
System.out.println("HashMap: " + hashTime / 1_000_000 + " ms");
// 测试遍历性能(保持顺序)
startTime = System.nanoTime();
for (Map.Entry<Integer, String> entry : linkedMap.entrySet()) {
// 模拟操作
}
linkedTime = System.nanoTime() - startTime;
System.out.println("\n遍历性能:");
System.out.println("LinkedHashMap: " + linkedTime / 1_000_000 + " ms");
}
}
实用技巧总结
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMapTips {
public static void main(String[] args) {
// 1. 反向迭代
LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);
System.out.println("反向迭代:");
String[] keys = map.keySet().toArray(new String[0]);
for (int i = keys.length - 1; i >= 0; i--) {
System.out.println(keys[i] + " -> " + map.get(keys[i]));
}
// 2. 获取第一个和最后一个元素
if (!map.isEmpty()) {
String firstKey = map.keySet().iterator().next();
System.out.println("\n第一个元素:" + firstKey + " -> " + map.get(firstKey));
}
// 3. 使用 computeIfAbsent
map.computeIfAbsent("D", k -> 4);
System.out.println("\n使用 computeIfAbsent 添加 D: " + map);
// 4. 批量操作
map.replaceAll((k, v) -> v * 2);
System.out.println("所有值乘以 2: " + map);
// 5. 安全的迭代删除
System.out.println("\n安全删除值小于 3 的元素:");
map.entrySet().removeIf(entry -> entry.getValue() < 3);
System.out.println(map);
}
}
使用建议
- 需要保持插入顺序:使用默认构造器
new LinkedHashMap<>() - 实现 LRU 缓存:使用
new LinkedHashMap<>(capacity, 0.75f, true)并重写removeEldestEntry - 内存考虑:LinkedHashMap 比 HashMap 多维护一个双向链表,占用更多内存
- 性能:基本操作与 HashMap 相近,迭代稍快(因为维护了链表)
- 线程安全:非线程安全,多线程环境需要使用
Collections.synchronizedMap()
这些案例涵盖了 LinkedHashMap 的主要使用场景,从简单的顺序保持到复杂的 LRU 缓存实现。