在Java中,Queue
是一个接口,它属于 java.util
包。Queue
接口继承自 Collection
接口,这意味着它是一个集合,但与普通的集合不同,它遵循先进先出(FIFO)的原则。队列主要用于维护元素的顺序,其中第一个插入的元素将是第一个被移除的。
以下是 Queue
接口的一些关键特性:
- 先进先出 (FIFO):队列中的元素按照它们被添加的顺序进行处理。
- 头部(Head):队列的第一个元素,它是下一个被移除的元素。
- 尾部(Tail):队列的最后一个元素,它是下一个被添加的元素(在某些实现中)。
- 容量:一些队列实现有固定容量,而其他实现则可以动态增长。
Queue
接口定义了一些方法,包括:
boolean add(E e)
:将元素添加到队列的尾部。如果成功,返回true
;如果队列满了,抛出IllegalStateException
。boolean offer(E e)
:将元素添加到队列的尾部,如果成功,返回true
;如果队列满了,返回false
,不会抛出异常。E remove()
:移除并返回队列头部的元素。如果队列为空,抛出NoSuchElementException
。E poll()
:移除并返回队列头部的元素,如果队列为空,返回null
,不会抛出异常。E element()
:返回队列头部的元素但不移除它。如果队列为空,抛出NoSuchElementException
。E peek()
:返回队列头部的元素但不移除它。如果队列为空,返回null
,不会抛出异常。
Java提供了几种 Queue
的实现:
ArrayDeque
:一个双端队列,可以用作栈或队列。LinkedList
:一个链表结构的队列,可以作为队列使用。PriorityQueue
:一个基于优先级的队列,元素根据其自然顺序或者构造时提供的Comparator
进行排序。DelayQueue
:一个使用优先级队列实现的无界阻塞队列,其中的元素只有在其指定的延迟到期时才能从队列中取走。ConcurrentLinkedQueue
:一个基于链接节点的无界线程安全队列。
使用队列时,你可以根据你的具体需求选择合适的实现。例如,如果你需要一个线程安全的队列,你可能会考虑使用 ConcurrentLinkedQueue
。如果你需要一个有固定容量的队列,你可能会使用 ArrayDeque
并设置其容量。
下面提供一些简单的Java代码示例,演示如何使用几种不同的Queue
实现。
使用ArrayDeque
作为队列
import java.util.ArrayDeque;
import java.util.Queue;
public class ArrayDequeExample {
public static void main(String[] args) {
Queue<Integer> queue = new ArrayDeque<>();
// 添加元素
queue.add(1);
queue.add(2);
queue.add(3);
// 移除并返回头部元素
System.out.println(queue.remove()); // 输出 1
// 查看但不移除头部元素
System.out.println(queue.peek()); // 输出 2
// 移除并返回头部元素
System.out.println(queue.poll()); // 输出 2
// 添加元素到队列尾部
queue.offer(4);
// 查看但不移除头部元素
System.out.println(queue.element()); // 输出 3
// 队列中的元素
System.out.println(queue); // 输出 [3, 4]
}
}
使用LinkedList
作为队列
import java.util.LinkedList;
import java.util.Queue;
public class LinkedListExample {
public static void main(String[] args) {
Queue<Integer> queue = new LinkedList<>();
// 添加元素
queue.add(1);
queue.add(2);
queue.add(3);
// 移除并返回头部元素
System.out.println(queue.remove()); // 输出 1
// 添加元素到队列尾部
queue.offer(4);
// 队列中的元素
System.out.println(queue); // 输出 [2, 3, 4]
}
}
使用PriorityQueue
作为优先级队列
import java.util.PriorityQueue;
public class PriorityQueueExample {
public static void main(String[] args) {
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
// 添加元素
priorityQueue.add(5);
priorityQueue.add(1);
priorityQueue.add(3);
// 移除并返回队列中优先级最高的元素(默认是最小的元素)
System.out.println(priorityQueue.remove()); // 输出 1
// 队列中的元素
System.out.println(priorityQueue); // 输出 [3, 5]
}
}
使用DelayQueue
延迟队列
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public class DelayQueueExample {
public static void main(String[] args) throws InterruptedException {
DelayQueue<MyDelayedObject> delayQueue = new DelayQueue<>();
// 添加元素到延迟队列
delayQueue.put(new MyDelayedObject(1, 2, TimeUnit.SECONDS));
delayQueue.put(new MyDelayedObject(2, 4, TimeUnit.SECONDS));
// 等待直到元素可用
MyDelayedObject element1 = delayQueue.take();
System.out.println("Taken from queue: " + element1); // 2秒后输出 MyDelayedObject{number=1, delay=2}
MyDelayedObject element2 = delayQueue.take();
System.out.println("Taken from queue: " + element2); // 4秒后输出 MyDelayedObject{number=2, delay=4}
}
static class MyDelayedObject implements Delayed {
private final int number;
private final long delay;
private final long deadline;
public MyDelayedObject(int number, long delay, TimeUnit timeUnit) {
this.number = number;
this.delay = delay;
this.deadline = System.currentTimeMillis() + timeUnit.toMillis(delay);
}
@Override
public long getDelay(TimeUnit unit) {
long delay = deadline - System.currentTimeMillis();
return unit.convert(delay, TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed other) {
if (this.deadline < ((MyDelayedObject) other).deadline) {
return -1;
}
if (this.deadline > ((MyDelayedObject) other).deadline) {
return 1;
}
return 0;
}
@Override
public String toString() {
return "MyDelayedObject{" + "number=" + number + ", delay=" + delay + '}';
}
}
}
使用ConcurrentLinkedQueue
作为线程安全的队列
import java.util.concurrent.ConcurrentLinkedQueue;
public class ConcurrentLinkedQueueExample {
public static void main(String[] args) {
ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<>();
// 添加元素
queue.add(1);
queue.add(2);
queue.add(3);
// 移除并返回头部元素
System.out.println(queue.poll()); // 输出 1
// 查看但不移除头部元素
System.out.println(queue.peek()); // 输出 2
// 队列中的元素
System.out.println(queue); // 输出 [2, 3]
}
}
这些示例展示了如何使用不同的队列实现来处理元素的添加、移除和查看操作。可以根据具体需求选择合适的队列实现。