Java 数据结构详解
Java 数据结构是 Java 编程中存储和组织数据的方式,就像现实生活中 “书架”“抽屉”“字典” 等工具 —— 不同的结构适合存放不同类型的数据,也决定了 “存、取、查” 的效率。Java 内置了一套完善的集合框架(Collection Framework),把常用数据结构封装成了易用的类,我们不需要从零实现,直接拿来用就行。
一、先搞懂:Java 集合框架的 “家谱”
Java 集合框架就像一个大家族,主要分为两大分支:
单值集合(Collection):每个元素是单个值(如数字、字符串),包括 List(有序可重复)、Set(无序不可重复);
键值对集合(Map):每个元素是 “键 - 值” 对(如字典中的 “单词 - 解释”),代表是 Map 接口。
它们的关系可以简单理解为:
集合框架
├─ Collection(单值集合)
│ ├─ List(有序、可重复)
│ │ ├─ ArrayList(数组实现)
│ │ └─ LinkedList(链表实现)
│ └─ Set(无序、不可重复)
│ ├─ HashSet(哈希表实现)
│ └─ TreeSet(红黑树实现,有序)
└─ Map(键值对集合)
├─ HashMap(哈希表实现)
└─ TreeMap(红黑树实现,键有序)
二、单值集合(Collection)详解
1. List:有序可重复的 “数组增强版”
List 就像一排有编号的抽屉,每个抽屉有固定位置(索引),可以放相同的东西(可重复)。你可以通过编号快速找到某个抽屉,也可以在任意位置添加 / 删除抽屉。
常用实现类:
ArrayList:底层是动态数组(长度可变的数组)。
优点:通过索引(如 get(0))访问元素极快(时间复杂度 O (1));
缺点:在中间插入 / 删除元素慢(需要移动后面的元素,时间复杂度 O (n));
类比:像一本书,查第 100 页很快,但在第 50 页插入一页,后面的页码都要变。
代码示例:
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
List
// 添加元素
list.add("苹果");
list.add("香蕉");
list.add("苹果"); // 允许重复
// 按索引访问(0 开始)
System.out.println(list.get(1)); // 输出:香蕉
// 遍历
for (String fruit : list) {
System.out.println(fruit); // 输出:苹果、香蕉、苹果(顺序和添加一致)
}
}
}
LinkedList:底层是双向链表(每个元素像 “铁链” 一样连在一起,每个节点记录前后节点的位置)。
优点:在中间插入 / 删除元素快(只需改前后节点的链接,时间复杂度 O (1));
缺点:通过索引访问慢(需要从头遍历到目标位置,时间复杂度 O (n));
类比:像一串项链,拆中间的珠子只需解开两边的线,但要找第 100 颗珠子,得从第一颗开始数。
2. Set:无序不可重复的 “去重神器”
Set 就像一个没有编号的袋子,里面的元素没有固定顺序,且不能有重复(比如 “黑名单” 里不能有重复的名字)。
常用实现类:
HashSet:底层是哈希表(通过 “哈希值” 快速定位元素)。
特点:无序(遍历顺序和添加顺序可能不同)、去重(依赖元素的 hashCode() 和 equals() 方法);
优点:添加、删除、查询速度极快(时间复杂度 O (1));
类比:像一本字典,通过拼音首字母(哈希值)快速找到单词,且不会有重复的单词。
代码示例:
import java.util.HashSet;
import java.util.Set;
public class Test {
public static void main(String[] args) {
Set
set.add("苹果");
set.add("香蕉");
set.add("苹果"); // 重复元素,会被自动过滤
// 遍历(顺序不确定)
for (String fruit : set) {
System.out.println(fruit); // 输出:苹果、香蕉(无重复)
}
}
}
TreeSet:底层是红黑树(一种自平衡的排序树)。
特点:自动按元素大小排序(如数字从小到大、字符串按字典序)、去重;
优点:适合需要 “排序 + 去重” 的场景(如排行榜);
缺点:添加 / 查询速度比 HashSet 稍慢(时间复杂度 O (log n))。
三、键值对集合(Map):像字典一样 “通过键找值”
Map 存储的是 “键(Key)- 值(Value)” 对,就像字典中 “单词(键)- 解释(值)” 的对应关系。键不能重复(一个单词只能有一个解释),但值可以重复(多个单词可以有相同解释)。
常用实现类:
HashMap:底层是哈希表(数组 + 链表 / 红黑树)。
特点:键无序、键唯一;
优点:根据键查询值的速度极快(O (1)),适合频繁的 “存、取” 操作;
类比:像手机通讯录,通过姓名(键)快速找到电话(值),姓名不能重复。
代码示例:
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) {
Map
// 存键值对
scoreMap.put("张三", 90);
scoreMap.put("李四", 85);
scoreMap.put("张三", 95); // 键重复,会覆盖之前的值
// 查值(通过键)
System.out.println(scoreMap.get("李四")); // 输出:85
// 遍历所有键值对
for (Map.Entry
System.out.println(entry.getKey() + ":" + entry.getValue());
// 输出:张三:95、李四:85(顺序不确定)
}
}
}
TreeMap:底层是红黑树。
特点:键会自动按大小排序(如数字键从小到大);
适合场景:需要按键排序的场景(如按学号排序的成绩表)。
四、其他常用数据结构
除了上述核心集合,Java 中还有一些特殊结构:
Queue(队列):“先进先出”(FIFO)的结构,像排队买票,先到先得。常用实现 LinkedList(因为链表适合频繁添加 / 删除)。
Queue
queue.offer("第一个人"); // 入队
queue.offer("第二个人");
System.out.println(queue.poll()); // 出队:第一个人(先入先出)
Stack(栈):“后进先出”(LIFO)的结构,像叠盘子,最后放的先拿走。Java 中常用 Deque 替代(LinkedList 实现)。
Deque
stack.push("第一层盘子"); // 入栈
stack.push("第二层盘子");
System.out.println(stack.pop()); // 出栈:第二层盘子(后入先出)
数组(Array):最基础的线性结构,长度固定,通过索引访问快,但不能动态扩容(ArrayList 是对数组的 “动态扩容” 封装)。
五、如何选择合适的数据结构?
记住几个核心场景:
需有序 + 可重复 + 频繁查:用 ArrayList;
需有序 + 可重复 + 频繁增删中间元素:用 LinkedList;
需去重 + 无序:用 HashSet;
需去重 + 排序:用 TreeSet;
需键值对 + 无序:用 HashMap;
需键值对 + 键排序:用 TreeMap;
需先进先出:用 Queue(LinkedList 实现);
需后进先出:用 Deque 当栈(LinkedList 实现)。
总结
Java 数据结构的核心是集合框架,它把复杂的底层实现(数组、链表、哈希表、红黑树等)封装成简单的类,我们只需关注 “用什么结构” 和 “怎么用”。
posted on
2025-08-29 09:10
coding博客
阅读(66)
评论(0)
收藏
举报