Java 常用数据结构:API + 实现类型 + 核心原理 + 例子 + 选型与性能(完整版)

Java 常用数据结构:API + 实现类型 + 核心原理 + 例子 + 选型与性能(完整版)

目标:把"怎么用(API)"和"为什么快/慢(实现原理)"放在同一份文档里。

约定:

  • 复杂度以 JDK 常见实现为准(均摊/平均),极端情况会更差。
  • 示例默认 import java.util.*;(并发类额外写全名)。
  • 推荐:左边接口,右边实现 (例如 Deque<Integer> dq = new ArrayDeque<>();)。

0) Java 集合框架总览(正确关系)

  • CollectionList / Set / Queue
  • DequeQueue 的子接口(双端队列,可当栈)
  • Map:独立体系,不属于 Collection

1) 数组 Array(T[] / int[]

实现类型与原理

  • JVM 原生连续内存(逻辑上连续),通过下标偏移寻址
  • 随机访问直接 O(1),插删需要整体搬移

常用 API/语法

  • a.length
  • a[i] 读写
  • Arrays.sort(a)
  • Arrays.binarySearch(a, key)
  • Arrays.copyOf(a, n)
  • System.arraycopy(...)

示例

java 复制代码
int[] a = {3, 1, 2};
Arrays.sort(a);                 // [1,2,3]
int idx = Arrays.binarySearch(a, 2); // 1

什么时候用

  • 原地算法、性能敏感、长度固定或可预估(计数、双指针、前缀和)

性能

  • 访问 O(1)
  • 中间插删 O(n)
  • 内存开销最低

2) List(有序、可重复、可按下标)

2.1 ArrayList(动态数组,最常用)

实现类型与原理
  • 底层:Object[] elementData
  • 扩容:容量不足时创建新数组 + System.arraycopy 拷贝
  • JDK 常用扩容策略:按比例增长(大致 1.5 倍,细节与版本有关)
  • 随机访问快;中间插删慢(搬移)
常用 API
  • add(e), add(i,e)
  • get(i), set(i,e)
  • remove(i), remove(obj)
  • size(), isEmpty(), clear()
  • contains, indexOf
  • subList(l,r)(视图,修改会影响原 list)
示例
java 复制代码
List<Integer> list = new ArrayList<>();
list.add(10);
list.add(20);
list.add(1, 15);     // [10,15,20]
int x = list.get(2); // 20
list.remove(Integer.valueOf(15));
什么时候用
  • 频繁 get/set、遍历、尾部追加
  • LeetCode 默认 list 选它
性能
  • get/set:O(1)
  • 尾插:均摊 O(1)
  • 中间插删:O(n)
  • 额外:扩容会有一次性 O(n) 拷贝

2.2 LinkedList(双向链表,实现 List + Deque)

实现类型与原理
  • 底层:双向链表节点 Node{E item; Node next; Node prev}
  • 头尾操作 O(1)
  • 随机访问 O(n)(要从头/尾走链)
  • 内存开销大(节点对象 + prev/next)
常用 API(Deque 语义更常用)
  • addFirst/addLast, offerFirst/offerLast
  • pollFirst/pollLast, removeFirst/removeLast
  • peekFirst/peekLast
示例
java 复制代码
LinkedList<Integer> ll = new LinkedList<>();
ll.addLast(1);
ll.addLast(2);
ll.addFirst(0);  // 0 1 2
int a = ll.pollFirst(); // 0
什么时候用
  • 需要频繁头尾增删且数据量不大
  • 但栈/队列更推荐 ArrayDeque
性能
  • 头尾增删:O(1)
  • get(i):O(n)
  • 内存:比 ArrayList/ArrayDeque 更重

2.3 Vector / Stack(历史遗留,不推荐)

  • Vector:动态数组 + 方法同步(锁开销)
  • Stack:继承 Vector,作为栈不如 ArrayDeque

3) Deque / Queue(栈、队列、双端队列)

3.1 ArrayDeque(栈/队列首选)

实现类型与原理
  • 底层:循环数组(环形缓冲区)Object[] elements
  • 维护 head/tail 下标,通过位运算/取模实现环形
  • 头尾增删无需搬移,O(1)
  • 扩容:数组满时重建更大数组并按顺序搬移一次
  • 不允许 null(用 null 作为空槽标记)
常用 API
  • 队列(FIFO):offer, poll, peek
  • 栈(LIFO):push, pop, peek
  • 双端:offerFirst/offerLast, pollFirst/pollLast, peekFirst/peekLast
示例(队列 + 栈)
java 复制代码
Deque<Integer> dq = new ArrayDeque<>();

// 队列
dq.offer(1);
dq.offer(2);
int q = dq.poll(); // 1

// 栈
dq.push(10);
dq.push(20);
int s = dq.pop();  // 20
什么时候用
  • BFS 队列、滑窗单调队列、单调栈、括号匹配、DFS 模拟栈
  • 几乎所有"栈/队列"刷题场景首选
性能
  • 头尾操作:O(1)
  • 通常快于 LinkedList,内存更省
  • 注意:pop() 空时抛异常,安全写法用 pollFirst() 判断

3.2 PriorityQueue(堆,优先队列)

实现类型与原理
  • 底层:数组实现的二叉堆(完全二叉树)
  • 默认:小根堆(最小值在堆顶)
  • offer:上浮(sift up)
  • poll:取顶后把末尾放顶再下沉(sift down)
  • 支持比较器自定义顺序
常用 API
  • offer/add, poll/remove, peek
  • size, isEmpty
示例(小根堆/大根堆)
java 复制代码
PriorityQueue<Integer> minH = new PriorityQueue<>();
minH.offer(3); minH.offer(1);
int a = minH.poll(); // 1

PriorityQueue<Integer> maxH = new PriorityQueue<>(Collections.reverseOrder());
maxH.offer(3); maxH.offer(1);
int b = maxH.poll(); // 3
什么时候用
  • TopK、实时最值、合并 K 路、Dijkstra/Prim、贪心调度
性能
  • 入/出堆:O(log n)
  • peek:O(1)
  • contains/删除任意元素:O(n)(不适合作 Set)

3.3 Queue 的并发实现(工程)

  • ConcurrentLinkedQueue:无锁非阻塞 FIFO(高并发)
  • LinkedBlockingQueue / ArrayBlockingQueue:阻塞队列(线程协作)
  • 原理涉及 CAS/锁/条件变量,通常不用于刷题

4) Set(去重集合)

4.1 HashSet(基于 HashMap)

实现类型与原理
  • 内部用 HashMap<E, Object> 存储元素作为 key

  • value 是固定哨兵对象(只占位)

  • 哈希表:数组 + 链表/红黑树(JDK8+)

    • 低碰撞:链表
    • 高碰撞:链表可能树化为红黑树(降低极端退化)
  • 依赖 hashCode()equals()

常用 API
  • add, remove, contains
  • size, isEmpty, clear
  • 遍历:for-each / iterator
示例
java 复制代码
Set<String> s = new HashSet<>();
s.add("a"); s.add("b");
boolean ok = s.contains("b");
s.remove("a");
什么时候用
  • 判重、集合运算、滑窗去重、两数之和判存在
性能
  • 平均 add/contains/remove:O(1)
  • 极端:碰撞很严重会变差(JDK8+ 有树化缓解)

4.2 LinkedHashSet(HashSet + 双向链表保持插入顺序)

实现类型与原理
  • 基于 LinkedHashMap
  • 在哈希表基础上维护双向链表,记录插入顺序
  • 遍历顺序稳定
示例
java 复制代码
Set<Integer> s = new LinkedHashSet<>();
s.add(3); s.add(1); s.add(2);
// 遍历:3,1,2
什么时候用
  • 去重 + 需要保持插入顺序输出
性能
  • 平均 O(1),略高于 HashSet(链表维护)

4.3 TreeSet(红黑树,有序集合)

实现类型与原理
  • 基于 TreeMap(元素作为 key)
  • 红黑树:平衡二叉搜索树,保证高度 O(log n)
  • 有序遍历、范围查询
常用 API(范围/邻近)
  • first/last
  • ceiling/floor/higher/lower
  • subSet/headSet/tailSet
示例
java 复制代码
TreeSet<Integer> ts = new TreeSet<>();
ts.add(3); ts.add(1); ts.add(2);
int c = ts.ceiling(2); // 2
什么时候用
  • 需要有序、范围查询(>=x 最小,<=x 最大)
性能
  • O(log n)

5) Map(键值映射)

5.1 HashMap(最常用)

实现类型与原理
  • 底层:哈希表数组 Node<K,V>[] table
  • key -> hash() -> 桶下标(index)
  • 桶内:链表(碰撞)或红黑树(JDK8+ 树化)
  • 扩容:resize(通常成倍扩),rehash 分布到新桶
  • 依赖 key 的 hashCode/equals
常用 API
  • put, get, remove
  • containsKey, getOrDefault
  • putIfAbsent
  • computeIfAbsent(懒加载/分组常用)
  • merge(计数合并常用)
  • 遍历:entrySet/keySet/values
示例(计数 + computeIfAbsent)
java 复制代码
Map<String, Integer> cnt = new HashMap<>();
String x = "a";
cnt.put(x, cnt.getOrDefault(x, 0) + 1);

Map<String, List<Integer>> group = new HashMap<>();
group.computeIfAbsent("k", k -> new ArrayList<>()).add(42);
什么时候用
  • 计数、映射、缓存、索引、分组(刷题最高频)
性能
  • 平均 O(1)
  • 扩容/rehash 会有一次性开销
  • key 自定义对象要正确实现 equals/hashCode

5.2 LinkedHashMap(有序 Map,可做 LRU)

实现类型与原理
  • 基于 HashMap + 双向链表

  • 可选:

    • 插入顺序(默认)
    • 访问顺序(accessOrder=true)用于 LRU
  • 重写 removeEldestEntry 可自动淘汰最老条目

示例(访问顺序)
java 复制代码
LinkedHashMap<Integer,Integer> m = new LinkedHashMap<>(16, 0.75f, true);
m.put(1,1); m.put(2,2);
m.get(1); // 1 变"最近访问"
什么时候用
  • 需要稳定遍历顺序
  • LRU 缓存
性能
  • 平均 O(1),略高开销

5.3 TreeMap(红黑树,有序 key)

实现类型与原理
  • 红黑树存 key,按自然顺序或 comparator 排序
  • 支持范围查询/邻近查询
常用 API
  • firstKey/lastKey
  • ceilingKey/floorKey/higherKey/lowerKey
  • subMap/headMap/tailMap
示例
java 复制代码
TreeMap<Integer,String> tm = new TreeMap<>();
tm.put(3,"c"); tm.put(1,"a"); tm.put(2,"b");
int k = tm.ceilingKey(2); // 2
什么时候用
  • 需要有序 key、区间操作(时间线/区间合并)
性能
  • O(log n)

5.4 ConcurrentHashMap(并发 Map,工程)

实现原理(高层)
  • 分段锁(旧)-> JDK8+ 以 CAS + synchronized 在桶级别控制
  • 目标:并发读写更高吞吐、避免全表锁
示例
java 复制代码
Map<String,Integer> m = new java.util.concurrent.ConcurrentHashMap<>();
m.merge("a", 1, Integer::sum);

6) BitSet(位集合,状态压缩)

实现类型与原理

  • 底层:long[](每个 long 64 位)
  • 通过位运算 set/get/and/or,内存极省

常用 API

  • set(i), clear(i), get(i)
  • and/or/xor, flip(i)
  • cardinality(), nextSetBit(i)

示例

java 复制代码
BitSet bs = new BitSet();
bs.set(10);
boolean ok = bs.get(10);

什么时候用

  • 大规模布尔标记、状态压缩 DP、位运算优化

性能

  • 位运算快;空间比 boolean[] 更省(但可读性略差)

7) StringBuilder(可变字符串)

实现原理

  • 底层:可扩容 char 数组(或 byte 数组,取决于 JDK 版本与编码实现)
  • append 时容量不够会扩容并复制

常用 API

  • append, insert, delete, reverse
  • charAt, setCharAt, length
  • toString

示例

java 复制代码
StringBuilder sb = new StringBuilder();
sb.append("ab").append(123);
String s = sb.toString();

什么时候用

  • 频繁拼接字符串(构造输出、路径、序列化)

性能

  • 避免 String 多次 + 产生大量临时对象

8) 刷题常用"组合结构"(用现有结构模拟)

8.1 单调栈(ArrayDeque)

  • 原理:维护栈内单调性,遇到破坏单调则弹出
  • 用途:下一个更大元素、最大矩形、接雨水
java 复制代码
Deque<Integer> st = new ArrayDeque<>();
for (int x : nums) {
    while (!st.isEmpty() && st.peek() > x) st.pop();
    st.push(x);
}

8.2 单调队列(滑窗最值)

  • 原理:队列内维护候选下标单调,过期弹出
java 复制代码
Deque<Integer> dq = new ArrayDeque<>();
for (int i = 0; i < n; i++) {
    while (!dq.isEmpty() && nums[dq.peekLast()] <= nums[i]) dq.pollLast();
    dq.offerLast(i);
    if (dq.peekFirst() <= i - k) dq.pollFirst();
    if (i >= k - 1) ans[i - k + 1] = nums[dq.peekFirst()];
}

9) 性能选型对照

目标 首选结构 原理关键词 复杂度要点
随机访问 + 尾插 ArrayList 动态数组/扩容 get O(1), 中间插删 O(n)
栈/队列/双端 ArrayDeque 环形数组 头尾 O(1)
TopK/最值流 PriorityQueue 二叉堆 offer/poll O(log n)
去重/判存在 HashSet 哈希表 平均 O(1)
计数/映射 HashMap 哈希表 平均 O(1)
有序/范围 TreeSet/TreeMap 红黑树 O(log n)
插入顺序稳定 LinkedHash* 哈希 + 双链表 平均 O(1)
省空间布尔标记 BitSet long 位数组 位操作

10) 关键坑点

  1. 声明类型决定可用方法

    • Queue q = new ArrayDeque<>(); 没有 push/pop
    • Deque dq = new ArrayDeque<>(); 才有 push/pop
  2. ArrayDeque 不允许 null(用 null 标记空槽)

  3. HashMap/HashSet 的 key 必须正确实现 equals/hashCode

  4. TreeMap/TreeSet 的 comparator 必须满足严格弱序,否则行为异常

  5. PriorityQueue 默认小根堆;大根堆要 comparator

  6. subList 是视图,修改会影响原 List

相关推荐
会游泳的石头2 小时前
构建企业级知识库智能问答系统:基于 Java 与 Spring Boot 的轻量实现
java·开发语言·spring boot·ai
Hx_Ma162 小时前
List 转二维 List
数据结构·windows·list
Full Stack Developme2 小时前
算法与数据结构,到底是怎么节省时间和空间的
数据结构·算法
BHXDML2 小时前
数据结构:(三)字符串——从暴力匹配到 KMP 的跨越
数据结构·算法
说给风听.2 小时前
Maven 配置实战:从环境搭建到 Idea 关联(超详细)
java·maven·intellij-idea
Hx_Ma162 小时前
SSM 项目中 mq是什么
java
生骨大头菜2 小时前
对接金蝶上传附件接口
java·开发语言
skywalker_112 小时前
File:路径详述
java·开发语言·file
老友@2 小时前
JMeter 在 Linux 环境下进行生产级性能压测的完整实战指南
java·linux·jmeter·性能优化·系统架构·压测·性能瓶颈