前言
这篇文章来和大家分享一下java集合框架与queue的使用.老话说,读书百遍其义自见.这是我第二次学习一些新的心得与理解.
一、java集合框架

- Java 集合框架是 Java 中用于存储和操作一组对象的体系,核心分为 Collection(单列集合)和Map(双列集合)
核心接口与分类
- Collection(单列集合)
- 是所有单列集合的根接口,定义了集合的基本操作(增删改查、遍历等)。
- 子接口:List(有序可重复)、Set(无序不可重复)、Queue(队列)。
- Map(双列集合)
- 存储键值对(Key-Value),Key 唯一、Value 可重复。
- 子接口:SortedMap(键有序)。
queue
- 在 Java 集合框架中,Queue(队列) 是继承自Collection的子接口,用于实现先进先出(FIFO) 的数据结构(部分实现类会打破 FIFO,如优先级队列)。它是处理 "按顺序排队" 场景的核心工具,比如任务调度、消息队列等。
- 一、核心特性
FIFO 原则:默认先入队的元素会先出队(部分实现类如PriorityQueue按优先级排序)。 - 双组操作方法:提供 "抛异常" 和 "返回特殊值" 两套方法,适配不同场景(如下表)。
- 可扩展:支持有界 / 无界队列,部分实现(如阻塞队列)支持多线程并发。
由于queue实现了linkedlist和arraylist的接口,可以使用他们两个来实现,不过一般是使用链表进行实现,下面也会手动实现一下~~
二、队列
- 在数据结构中,顺序表是用连续的存储单元存储元素的线性表,而 Java 中的ArrayList就是顺序表的具体实现,下面从数据结构方面介绍:
基本解释
- 队列(Queue)是一种先进先出 (FIFO, First In First Out) 的线性数据结构,它的操作遵循 "先进入队列的元素,先出队列" 的规则,就像日常生活中排队买票、排队结账的场景。
核心操作
队列的操作主要围绕队首(出队端)和队尾(入队端)展开,基本操作分为 4 类:
- 入队(Enqueue):在队尾添加一个元素。
- 出队(Dequeue):从队首移除并返回一个元素。
- 查看队首(Peek/Front):返回队首元素,但不移除它。
- 判空 / 判满:判断队列是否为空,或是否已满(仅针对有界队列)。
队列的分类
根据不同的标准,队列可以分为多种类型:
我们主要是看一下按存储结构分
- 顺序队列:基于数组实现,通常会设计成循环队列来解决 "假溢出" 问题(即队尾到达数组末尾,但队首前方还有空闲空间)。
- 链式队列:基于链表实现,没有固定容量限制,元素入队时直接在链表尾部追加节点,出队时删除链表头部节点。
三、典型应用场景
任务调度:比如操作系统的进程调度、打印机的任务排队。
消息队列:分布式系统中,用于解耦生产者和消费者,削峰填谷。
广度优先搜索(BFS):算法中常用队列存储待访问的节点,逐层遍历图或树。
缓存淘汰:部分缓存策略(如 FIFO 缓存)基于队列实现。
三、常用代码手动实现

- 这一部分的逻辑是较为简单的,小伙伴们如果是第一次接触,非常建议大家上手实现一下~
我就都分成一个一个小的代码块了 大家在学习的时候也可以分成基本成员变量 ,成员方法,**辅助方法(在成员方法中被调用的小方法)**进行学习
基本方法
java
// 节点类:存储数据和下一个节点的引用
class Node<E> {
E data;
Node<E> next;
public Node(E data) {
this.data = data;
this.next = null;
}
}
// 链表队列
public class LinkedQueue<E> {
// 队首指针(指向头节点)、队尾指针(指向尾节点)
private Node<E> front;
private Node<E> rear;
// 队列元素个数
private int size;
// 构造方法:初始化空队列
public LinkedQueue() {
this.front = null;
this.rear = null;
this.size = 0;
}
/**
* 入队:队尾添加元素
* @param e 要添加的元素
* @return 永远返回true(链表无界)
*/
public boolean offer(E e) {
Node<E> newNode = new Node<>(e);
if (isEmpty()) {
// 空队列时,头尾指针都指向新节点
front = newNode;
rear = newNode;
} else {
// 非空队列时,尾节点的next指向新节点,更新尾指针
rear.next = newNode;
rear = newNode;
}
size++;
return true;
}
/**
* 出队:移除并返回队首元素
* @return 队首元素,队空返回null
*/
public E poll() {
if (isEmpty()) {
return null;
}
// 取出队首数据
E value = front.data;
// 头指针后移
front = front.next;
size--;
// 如果队列为空,尾指针也要置空
if (isEmpty()) {
rear = null;
}
return value;
}
/**
* 查看队首元素(不移除)
* @return 队首元素,队空返回null
*/
public E peek() {
if (isEmpty()) {
return null;
}
return front.data;
}
// 判断队列是否为空
public boolean isEmpty() {
return size == 0;
}
// 获取队列元素个数
public int size() {
return size;
}
四、顺序表实现队列(环形队列)
-
上面我们是用链表的形式实现的,数组实现也是重要的形式,有着高效的查找能力等优点,不过我们要想通过顺序表的形式进行面临着两个直观的问题.

-
第一
一个数组在物理上不是圆形的,当一个存在元素的队列出队时,就会存在空间的浪费,我们在入队是不是简单的下表+1了.
实际上我们可以 "取模运算" 让下标 "循环移动",把数组 "逻辑上变成环形",避免出队后的空间浪费。比如
- 初始时front=0,rear=0(队空)。
- 入队 3 个元素后,rear=3(元素存在0、1、2下标)。
- 出队 1 个元素,front=1(此时0下标空了)。
- 再入队时,rear = (3+1) % 4 = 0(把新元素存到0下标,复用了出队空出的空间)。
-
第二
既然是环形的那怎样是满了呢,或者说如何标记队列满了?
实际上循环队列通过 "牺牲 1 个数组空间" 来区分 "队空" 和 "队满":
- 队空条件:front == rear(头尾指针重合)。
- 队满条件:(rear + 1) % 数组长度 == front(尾指针的 "下一个位置" 是头指针)。
代码实现
java
public class CircularQueue<E> {
private final Object[] arr;
private int front; // 队首指针
private int rear; // 队尾指针
private final int len; // 数组长度(=实际可存元素数+1)
public CircularQueue(int maxSize) {
this.len = maxSize + 1; // 牺牲1个空间
this.arr = new Object[len];
this.front = 0;
this.rear = 0;
}
// 入队:复用空间(取模实现环形)
public boolean offer(E e) {
if ((rear + 1) % len == front) {
return false; // 队满
}
arr[rear] = e;
rear = (rear + 1) % len; // 循环移动下标
return true;
}
// 出队
@SuppressWarnings("unchecked")
public E poll() {
if (front == rear) {
return null; // 队空
}
E value = (E) arr[front];
front = (front + 1) % len; // 循环移动下标
return value;
}
}
总结
- 到这里我的分享就先结束了~,希望对你有帮助
- 我是dylan 下次见~
- 无限进步

- 无限进步