🌈个人主页 :一条泥憨鱼 (欢迎各位大佬莅临)

前言:
在学习 Java 集合框架时,很多同学已经接触过 HashMap。
但在实际开发中,我们还会经常遇到另外两种 Map:
-
LinkedHashMap -
TreeMap
它们都属于 Map 接口的实现类,但各自有不同的特点和使用场景。
这篇文章会从:
基本概念
底层原理
特点区别
使用场景
代码实例
几个方面,帮你彻底理解它们。
一、Map 集合基础回顾
Map 是"键值对(key-value)"结构的数据集合。
格式:
java
key -> value
例如:
java
"张三" -> 18
"李四" -> 20
Java 中常见的 Map:
| 类型 | 特点 |
|---|---|
| HashMap | 无序 |
| LinkedHashMap | 有序 |
| TreeMap | 自动排序 |
二、LinkedHashMap
1. 什么是 LinkedHashMap
LinkedHashMap 是 HashMap 的子类。
它最大的特点:
能够保持元素的插入顺序。
例如:
1 -> A
3 -> C
2 -> B
遍历时仍然是:
1
3
2
不会像 HashMap 一样顺序混乱。
2. LinkedHashMap 底层原理
LinkedHashMap = HashMap + 双向链表
它内部:
-
使用 HashMap 进行存储
-
使用双向链表维护顺序
结构示意:
数组 + 链表 + 红黑树 + 双向链表
其中:
-
HashMap 保证查询效率
-
双向链表保证顺序
3. LinkedHashMap 的特点
| 特点 | 说明 |
|---|---|
| 有序 | 按插入顺序排列 |
| 查询快 | 基于 HashMap |
| 允许 null | key 和 value 都允许 |
| 非线程安全 | 多线程需额外处理 |
4. LinkedHashMap 基本使用
示例:保持插入顺序
java
import java.util.LinkedHashMap;
public class Demo {
public static void main(String[] args) {
LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
map.put(3, "Java");
map.put(1, "Python");
map.put(2, "C++");
System.out.println(map);
}
}
输出:
java
{3=Java, 1=Python, 2=C++}
可以发现:
顺序与插入顺序一致。
5. 遍历 LinkedHashMap
java
import java.util.LinkedHashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) {
LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
map.put(1, "张三");
map.put(2, "李四");
map.put(3, "王五");
for (Map.Entry<Integer, String> entry : map.entrySet()) {
System.out.println(
entry.getKey() + " : " + entry.getValue()
);
}
}
}
输出:
java
1 : 张三
2 : 李四
3 : 王五
6. LinkedHashMap 的访问顺序
LinkedHashMap 有两种顺序:
| 顺序 | 说明 |
|---|---|
| 插入顺序 | 默认 |
| 访问顺序 | 最近访问的排后面 |
开启方式:
java
new LinkedHashMap<>(16,0.75f,true)
第三个参数"true"表示开启访问顺序。
示例:LRU缓存思想
java
import java.util.LinkedHashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) {
LinkedHashMap<Integer, String> map =
new LinkedHashMap<>(16, 0.75f, true);
map.put(1, "A");
map.put(2, "B");
map.put(3, "C");
//访问元素
map.get(1);
System.out.println(map);
}
}
输出:
{2=B, 3=C, 1=A}
因为:
1
**被访问后移动到了最后,**这就是很多缓存系统的核心思想。
三、TreeMap
1. 什么是 TreeMap
TreeMap 的最大特点:
自动排序。
无论你插入顺序如何,它都会自动按照 key 排序。
2. TreeMap 底层原理
TreeMap 底层采用:
红黑树(Red-Black Tree)
红黑树本质:
自平衡二叉搜索树。
特点:
查询效率高
自动排序
增删改效率稳定
时间复杂度:
| 操作 | 时间复杂度 |
|---|---|
| put | O(log n) |
| get | O(log n) |
| remove | O(log n) |
3. TreeMap 的特点
| 特点 | 说明 |
|---|---|
| 自动排序 | 按 key 排序 |
| 不允许 key 为 null | 会报空指针异常 |
| 查询效率稳定 | 红黑树实现 |
| 非线程安全 | 多线程需同步 |
四、TreeMap 默认排序
默认按照 key 的自然顺序排序。
示例:数字排序
java
import java.util.TreeMap;
public class Demo {
public static void main(String[] args) {
TreeMap<Integer, String> map = new TreeMap<>();
map.put(3, "Java");
map.put(1, "Python");
map.put(2, "C++");
System.out.println(map);
}
}
输出:
java
{1=Python, 2=C++, 3=Java}
即使插入顺序:
3 1 2
结果仍然自动排序。
五、TreeMap 字符串排序
java
import java.util.TreeMap;
public class Demo {
public static void main(String[] args) {
TreeMap<String, Integer> map = new TreeMap<>();
map.put("banana", 1);
map.put("apple", 2);
map.put("cat", 3);
System.out.println(map);
}
}
输出:
java
{apple=2, banana=1, cat=3}
按照字母顺序排序。
六、TreeMap 自定义排序
TreeMap 可以通过:
Comparator 比较器
实现自定义排序。
示例:降序排序
java
import java.util.Comparator;
import java.util.TreeMap;
public class Demo {
public static void main(String[] args) {
TreeMap<Integer, String> map =
new TreeMap<>(Comparator.reverseOrder());
map.put(1, "A");
map.put(3, "C");
map.put(2, "B");
System.out.println(map);
}
}
输出:
java
{3=C, 2=B, 1=A}
七、TreeMap 自定义对象排序
如果 key 是对象,则必须实现:
-
Comparable
或 -
Comparator
否则会报错。
示例:学生年龄排序
Student 类
java
class Student {
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + "-" + age;
}
}
使用 Comparator
java
import java.util.Comparator;
import java.util.TreeMap;
public class Demo {
public static void main(String[] args) {
TreeMap<Student, String> map =
new TreeMap<>((o1, o2) -> o1.age - o2.age);
map.put(new Student("张三", 18), "Java");
map.put(new Student("李四", 20), "Python");
map.put(new Student("王五", 19), "C++");
System.out.println(map);
}
}
输出:
java
{张三-18=Java, 王五-19=C++, 李四-20=Python}
八、LinkedHashMap 与 TreeMap 对比
| 对比项 | LinkedHashMap | TreeMap |
|---|---|---|
| 是否有序 | 按插入顺序 | 自动排序 |
| 底层结构 | Hash表 + 双向链表 | 红黑树 |
| 查询效率 | O(1) | O(log n) |
| 是否允许 null key | 允许 | 不允许 |
| 使用场景 | 记录顺序 | 排序需求 |
九、如何选择?
使用 LinkedHashMap
-
需要保持插入顺序
-
最近访问记录
-
LRU缓存
-
浏览历史
例如:
最近播放歌曲
最近浏览商品
使用 TreeMap
-
自动排序
-
排行榜
-
成绩排序
-
字典排序
例如:
学生成绩排名
商品价格排序
十、小tips
1. LinkedHashMap 和 HashMap 区别?
LinkedHashMap:
-
有顺序
-
多了双向链表
HashMap:
-
无序
-
纯哈希结构
2. TreeMap 为什么能排序?
因为底层是红黑树
插入元素时会自动比较 key。
3. TreeMap 为什么不能为 null?
因为排序时需要比较 key:
java
compareTo()
null 无法比较。
4. LinkedHashMap 为什么适合做缓存?
因为它支持:
访问顺序
最近访问的数据会移动到尾部。
这正符合:
LRU(使用少)
缓存淘汰策略。
十一、总结
LinkedHashMap
核心关键词:
有序
插入顺序
双向链表
缓存
适合:
既想要 HashMap 的效率,又想保持顺序。
TreeMap
核心关键词:
自动排序
红黑树
比较器
有序Map
适合:
需要按 key 自动排序的场景。
十二、用一张图来表示三种map
Map
├── HashMap
│ ├── 无序
│ └── 查询快
│
├── LinkedHashMap
│ ├── 有序
│ ├── 双向链表
│ └── 适合缓存
│
└── TreeMap
├── 自动排序
├── 红黑树
└── 适合排行榜
真正掌握集合框架后,其实我们会发现:
Java 集合本质就是:
"数据结构 + 算法思想" 的具体实现。