1. 栈与队列的基础认知
第一次接触数据结构时,导师在黑板上画了两个图形:一个垂直的筒子(栈)和一条水平的管道(队列)。这个场景我记了十几年,因为这两种结构实在太经典了。栈就像我们叠盘子,最后放上去的总是最先被拿走(LIFO);而队列则像排队买奶茶,先来的顾客先得到服务(FIFO)。在Java中实现它们,不仅是语法练习,更是理解计算机如何处理数据流的绝佳入口。
实际开发中,栈的身影无处不在:方法调用时的调用栈、IDE的撤销操作、浏览器的前进后退;队列则在任务调度、消息传递等场景大显身手。虽然Java集合框架已经提供了成熟的实现(java.util.Stack和java.util.Queue),但亲手实现一次,你会对源码设计有更深的体会。去年优化一个交易系统时,正是对队列实现的深入理解,帮我定位到了线程阻塞的症结所在。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 栈的Java实现剖析
2.1 基于数组的定容栈
定容栈的实现就像给储物柜分配固定格子。我们先定义存储数据的数组和栈顶指针:
java复制public class FixedCapacityStack<T> {
private T[] items;
private int top; // 栈顶指针(下一个空位索引)
@SuppressWarnings("unchecked")
public FixedCapacityStack(int capacity) {
items = (T[]) new Object[capacity]; // Java不允许直接创建泛型数组
top = 0;
}
}
关键操作的核心逻辑:
- push():检查溢出后存入数据并移动指针
- pop():检查下溢后返回数据并移动指针
- peek():仅查看不弹出
java复制public void push(T item) {
if (top == items.length) {
throw new RuntimeException("Stack overflow");
}
items[top++] = item;
}
public T pop() {
if (isEmpty()) {
throw new RuntimeException("Stack underflow");
}
return items[--top]; // 注意前置递减
}
实际工程中更推荐使用动态扩容策略。当数组填满时,创建一个更大的数组并复制元素,类似ArrayList的实现机制。
2.2 基于链表的动态栈
链式栈就像用绳子串起的珠子,每个节点记住下一个节点的位置:
java复制private static class Node<T> {
T data;
Node<T> nex
