Java?LinkedHashMap與TreeMap示例詳解
前言:
在學(xué)習(xí) Java 集合框架時,很多同學(xué)已經(jīng)接觸過 HashMap。
但在實際開發(fā)中,我們還會經(jīng)常遇到另外兩種 Map:
- LinkedHashMap
- TreeMap
它們都屬于 Map 接口的實現(xiàn)類,但各自有不同的特點和使用場景。
這篇文章會從:
- 基本概念
- 底層原理
- 特點區(qū)別
- 使用場景
- 代碼實例
幾個方面,幫你徹底理解它們。
一、Map 集合基礎(chǔ)回顧
Map 是“鍵值對(key-value)”結(jié)構(gòu)的數(shù)據(jù)集合。
格式:
key -> value
例如:
"張三" -> 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 + 雙向鏈表
它內(nèi)部:
- 使用 HashMap 進行存儲
- 使用雙向鏈表維護順序
結(jié)構(gòu)示意:
數(shù)組 + 鏈表 + 紅黑樹 + 雙向鏈表
其中:
- HashMap 保證查詢效率
- 雙向鏈表保證順序
3. LinkedHashMap 的特點
| 特點 | 說明 |
|---|---|
| 有序 | 按插入順序排列 |
| 查詢快 | 基于 HashMap |
| 允許 null | key 和 value 都允許 |
| 非線程安全 | 多線程需額外處理 |
4. LinkedHashMap 基本使用
示例:保持插入順序
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);
}
}輸出:
{3=Java, 1=Python, 2=C++}
可以發(fā)現(xiàn):
順序與插入順序一致。
5. 遍歷 LinkedHashMap
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()
);
}
}
}輸出:
1 : 張三
2 : 李四
3 : 王五
6. LinkedHashMap 的訪問順序
LinkedHashMap 有兩種順序:
| 順序 | 說明 |
|---|---|
| 插入順序 | 默認(rèn) |
| 訪問順序 | 最近訪問的排后面 |
開啟方式:
new LinkedHashMap<>(16,0.75f,true)
第三個參數(shù)“true”表示開啟訪問順序。
示例:LRU緩存思想
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
被訪問后移動到了最后,這就是很多緩存系統(tǒng)的核心思想。
三、TreeMap
1. 什么是 TreeMap
TreeMap 的最大特點:
自動排序。
無論你插入順序如何,它都會自動按照 key 排序。
2. TreeMap 底層原理
TreeMap 底層采用:
紅黑樹(Red-Black Tree)
紅黑樹本質(zhì):
自平衡二叉搜索樹。
特點:
- 查詢效率高
- 自動排序
- 增刪改效率穩(wěn)定
時間復(fù)雜度:
| 操作 | 時間復(fù)雜度 |
|---|---|
| put | O(log n) |
| get | O(log n) |
| remove | O(log n) |
3. TreeMap 的特點
| 特點 | 說明 |
|---|---|
| 自動排序 | 按 key 排序 |
| 不允許 key 為 null | 會報空指針異常 |
| 查詢效率穩(wěn)定 | 紅黑樹實現(xiàn) |
| 非線程安全 | 多線程需同步 |
四、TreeMap 默認(rèn)排序
默認(rèn)按照 key 的自然順序排序。
示例:數(shù)字排序
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);
}
}輸出:
{1=Python, 2=C++, 3=Java}
即使插入順序:
3 1 2
結(jié)果仍然自動排序。
五、TreeMap 字符串排序
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);
}
}輸出:
{apple=2, banana=1, cat=3}
按照字母順序排序。
六、TreeMap 自定義排序
TreeMap 可以通過:
Comparator 比較器
實現(xiàn)自定義排序。
示例:降序排序
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);
}
}輸出:
{3=C, 2=B, 1=A}
七、TreeMap 自定義對象排序
如果 key 是對象,則必須實現(xiàn):
- Comparable
- 或
- Comparator
否則會報錯。
示例:學(xué)生年齡排序
Student 類
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
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);
}
}輸出:
{張三-18=Java, 王五-19=C++, 李四-20=Python}
八、LinkedHashMap 與 TreeMap 對比
| 對比項 | LinkedHashMap | TreeMap |
|---|---|---|
| 是否有序 | 按插入順序 | 自動排序 |
| 底層結(jié)構(gòu) | Hash表 + 雙向鏈表 | 紅黑樹 |
| 查詢效率 | O(1) | O(log n) |
| 是否允許 null key | 允許 | 不允許 |
| 使用場景 | 記錄順序 | 排序需求 |
九、如何選擇?
使用 LinkedHashMap
- 需要保持插入順序
- 最近訪問記錄
- LRU緩存
- 瀏覽歷史
例如:
最近播放歌曲 最近瀏覽商品
使用 TreeMap
- 自動排序
- 排行榜
- 成績排序
- 字典排序
例如:
學(xué)生成績排名 商品價格排序
十、小tips
1. LinkedHashMap 和 HashMap 區(qū)別?
LinkedHashMap:
- 有順序
- 多了雙向鏈表
HashMap:
- 無序
- 純哈希結(jié)構(gòu)
2. TreeMap 為什么能排序?
因為底層是紅黑樹
插入元素時會自動比較 key。
3. TreeMap 為什么不能為 null?
因為排序時需要比較 key:
compareTo()
null 無法比較。
4. LinkedHashMap 為什么適合做緩存?
因為它支持:
訪問順序
最近訪問的數(shù)據(jù)會移動到尾部。
這正符合:
LRU(使用少)
緩存淘汰策略。
十一、總結(jié)
LinkedHashMap
核心關(guān)鍵詞:
有序 插入順序 雙向鏈表 緩存
適合:
既想要 HashMap 的效率,又想保持順序。
TreeMap
核心關(guān)鍵詞:
自動排序 紅黑樹 比較器 有序Map
適合:
需要按 key 自動排序的場景。
十二、用一張圖來表示三種map
Map
├── HashMap
│ ├── 無序
│ └── 查詢快
│
├── LinkedHashMap
│ ├── 有序
│ ├── 雙向鏈表
│ └── 適合緩存
│
└── TreeMap
├── 自動排序
├── 紅黑樹
└── 適合排行榜真正掌握集合框架后,其實我們會發(fā)現(xiàn):
Java 集合本質(zhì)就是:
“數(shù)據(jù)結(jié)構(gòu) + 算法思想” 的具體實現(xiàn)。
到此這篇關(guān)于Java LinkedHashMap與TreeMap的文章就介紹到這了,更多相關(guān)Java LinkedHashMap與TreeMap內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
老生常談Java中instanceof關(guān)鍵字的理解
java 中的instanceof 運算符是用來在運行時指出對象是否是特定類的一個實例。這篇文章主要介紹了老生常談Java中instanceof關(guān)鍵字的理解,需要的朋友可以參考下2018-10-10
Java優(yōu)雅實現(xiàn)判空方法(結(jié)合實際案例)
相信寫過代碼的朋友們都會進行一個非空判斷,但是各種非空判斷中,那種才是最優(yōu)雅,最高效的呢,這篇文章主要介紹了Java優(yōu)雅實現(xiàn)判空方法的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-06-06
Spring Boot 中PageHelper 插件使用配置思路詳解
這篇文章主要介紹了Spring Boot 中PageHelper 插件使用配置及實現(xiàn)思路,通過引入myabtis和pagehelper依賴,在yml中配置mybatis掃描和實體類,具體實現(xiàn)方法跟隨小編一起看看吧2021-08-08
springboot統(tǒng)一異常處理(返回json)并格式化異常
這篇文章主要介紹了springboot統(tǒng)一異常處理(返回json)并格式化異常,對spring boot的默認(rèn)異常處理方式進行修改,要統(tǒng)一返回數(shù)據(jù)格式,優(yōu)雅的數(shù)據(jù)交互,優(yōu)雅的開發(fā)應(yīng)用,需要的朋友可以參考下2023-07-07

