赞
踩
hi,我是程序员王也,一个资深Java开发工程师,平时十分热衷于技术副业变现和各种搞钱项目的程序员~,如果你也是,可以一起交流交流。
今天我们来聊聊Java中的队列(Queue)~
队列(Queue)是一种特殊类型的集合,它遵循先进先出(FIFO - First In First Out)原则,这意味着第一个添加到队列的元素将是第一个被移除的元素。
FIFO原则是队列操作的核心。在队列中,元素只能从队尾(rear)添加,从队头(front)移除。这种操作方式确保了先进入队列的元素先被取出。
队列的基本操作通常包括:
下面是一个简单的队列实现示例,使用Java的LinkedList
作为底层数据结构,因为LinkedList
提供了高效的添加和移除操作。
import java.util.LinkedList; public class SimpleQueue<T> { private LinkedList<T> list = new LinkedList<>(); public void enqueue(T element) { list.addLast(element); } public T dequeue() { if (isEmpty()) { throw new IllegalStateException("Queue is empty"); } return list.removeFirst(); } public T peek() { if (isEmpty()) { throw new IllegalStateException("Queue is empty"); } return list.getFirst(); } public boolean isEmpty() { return list.isEmpty(); } public static void main(String[] args) { SimpleQueue<String> queue = new SimpleQueue<>(); queue.enqueue("Alice"); queue.enqueue("Bob"); queue.enqueue("Charlie"); System.out.println(queue.dequeue()); // 输出: Alice System.out.println(queue.peek()); // 输出: Bob System.out.println(queue.dequeue()); // 输出: Bob System.out.println(queue.dequeue()); // 输出: Charlie System.out.println(queue.isEmpty()); // 输出: true } }
在Java中,Queue
接口定义了队列操作的行为。它扩展了Collection
接口,并添加了一些队列特有的方法。以下是Queue
接口的一些基本方法:
boolean add(E e)
: 向队列添加一个元素。如果不能添加,会抛出IllegalStateException
。boolean offer(E e)
: 添加一个元素到队列,如果成功返回true
,否则返回false
。E remove()
: 移除并返回队列头部的元素。如果不能移除,会抛出NoSuchElementException
。E poll()
: 移除并返回队列头部的元素,如果没有元素则返回null
。E element()
: 返回队列头部的元素但不移除它。如果不能获取,会抛出NoSuchElementException
。E peek()
: 返回队列头部的元素但不移除它,如果没有元素则返回null
。与List
和Set
不同,Queue
提供了一种特定的集合顺序,即FIFO(先进先出)。List
允许对序列进行随机访问,而Set
不允许有重复的元素。相比之下,Queue
更注重元素的添加和移除操作。
下面是一个使用Java Queue
接口的示例,我们将使用LinkedList
作为队列的实现:
import java.util.LinkedList; import java.util.Queue; public class QueueExample { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); // 向队列中添加元素 queue.add("First"); queue.add("Second"); queue.add("Third"); // 使用remove方法移除并获取队头元素 System.out.println(queue.remove()); // 输出: First // 使用poll方法移除并获取队头元素,如果没有元素则返回null System.out.println(queue.poll()); // 输出: Second // 使用element方法获取队头元素但不移除 System.out.println(queue.element()); // 输出: Third // 使用peek方法获取队头元素但不移除,如果为空则返回null System.out.println(queue.peek()); // 输出: Third // 再次使用remove方法移除剩余的元素 System.out.println(queue.remove()); // 输出: Third System.out.println(queue.remove()); // 抛出: NoSuchElementException } }
在Java中,Queue
接口有多个实现类,每个实现类都有其特定的用途和性能特点。以下是几个常用的Queue
实现类:
ArrayDeque
是一个双端队列,可以作为一个队列或者栈使用。它允许元素从两端添加或移除。
LinkedList
实现的Queue
提供了高效的元素添加、移除操作,但可能不如ArrayDeque
在队列操作中的性能表现。
PriorityQueue
是一个不允许null
元素的队列,它按照自然排序顺序或者根据提供的Comparator
来决定元素的顺序。
ArrayDeque
:适合需要从两端进行操作的场景,如滑动窗口问题。LinkedList
:适合需要频繁插入和删除的场景,但可能在队列操作中不如ArrayDeque
高效。PriorityQueue
:适合需要根据优先级来访问元素的场景。import java.util.ArrayDeque; public class ArrayDequeExample { public static void main(String[] args) { ArrayDeque<Integer> deque = new ArrayDeque<>(); // 向队列两端添加元素 deque.addLast(1); deque.addLast(2); deque.addFirst(0); // 从队列两端移除元素 System.out.println(deque.removeFirst()); // 输出: 0 System.out.println(deque.removeLast()); // 输出: 2 } }
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); // 使用poll和peek方法 System.out.println(queue.poll()); // 输出: 1 System.out.println(queue.peek()); // 输出: 2 } }
import java.util.PriorityQueue; public class PriorityQueueExample { public static void main(String[] args) { PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(); // 向优先队列添加元素 priorityQueue.offer(10); priorityQueue.offer(1); priorityQueue.offer(5); // 按优先级移除元素 while (!priorityQueue.isEmpty()) { System.out.println(priorityQueue.poll()); // 输出: 1, 5, 10 } } }
在软件开发中,队列(Queue)是一种非常有用的数据结构,它在多种场景下都有应用。以下是一些典型的应用场景:
队列常用于任务调度系统中,其中任务按照它们被添加的顺序执行。例如,一个打印队列可以确保打印任务按照提交的顺序进行。
在分布式系统中,消息队列用于在不同服务或组件之间传递消息。消息队列可以作为缓冲区,平衡生产者和消费者之间的速率。
队列还可以用于缓冲处理,例如在网络编程中,当处理速度跟不上数据到达速度时,可以使用队列临时存储数据。
import java.util.concurrent.LinkedBlockingQueue; public class TaskScheduler { private final LinkedBlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>(); public void addTask(Runnable task) { taskQueue.offer(() -> { System.out.println("Executing task: " + task); task.run(); }); } public void startScheduling() { new Thread(() -> { while (!Thread.currentThread().isInterrupted()) { try { taskQueue.take().run(); } catch (InterruptedException e) { break; } } }).start(); } public static void main(String[] args) { TaskScheduler scheduler = new TaskScheduler(); scheduler.addTask(() -> System.out.println("Task 1")); scheduler.addTask(() -> System.out.println("Task 2")); scheduler.startScheduling(); } }
在这个任务调度的示例中,我们创建了一个TaskScheduler
,它使用LinkedBlockingQueue
作为任务队列。每个任务被包装成一个新的Runnable
,然后添加到队列中。调度器线程从队列中取出任务并执行它们。
import java.util.concurrent.DelayQueue; public class MessageQueue { private final DelayQueue<ScheduledMessage> messageQueue = new DelayQueue<>(); public void sendMessage(ScheduledMessage message) { messageQueue.put(message); } public void startMessageHandling() { new Thread(() -> { try { while (!Thread.currentThread().isInterrupted()) { ScheduledMessage message = messageQueue.take(); System.out.println("Handling message: " + message.getMessage()); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }).start(); } static class ScheduledMessage { private final long scheduledTime; private final String message; public ScheduledMessage(long scheduledTime, String message) { this.scheduledTime = scheduledTime; this.message = message; } public long getScheduledTime() { return scheduledTime; } public String getMessage() { return message; } } public static void main(String[] args) { MessageQueue messageQueue = new MessageQueue(); messageQueue.sendMessage(new ScheduledMessage(System.currentTimeMillis() + 5000, "Hello")); messageQueue.sendMessage(new ScheduledMessage(System.currentTimeMillis() + 10000, "World")); messageQueue.startMessageHandling(); } }
在这个消息队列的示例中,我们使用了DelayQueue
来存储带有一定延迟的消息。每个ScheduledMessage
都有一个预定的时间戳,它将在那个时间戳之后变得可用。消息处理线程使用take
方法从队列中取出并处理消息。
import java.util.LinkedList; import java.util.Queue; public class BufferProcessor<T> { private final Queue<T> buffer = new LinkedList<>(); private final int capacity; public BufferProcessor(int capacity) { this.capacity = capacity; } public void addElement(T element) { synchronized (buffer) { while (buffer.size() == capacity) { try { buffer.wait(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; } } buffer.add(element); buffer.notifyAll(); } } public T removeElement() { synchronized (buffer) { while (buffer.isEmpty()) { try { buffer.wait(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return null; } } buffer.notifyAll(); return buffer.remove(); } } }
在这个缓冲处理的示例中,我们创建了一个BufferProcessor
类,它使用LinkedList
作为缓冲区。addElement
方法用于向缓冲区添加元素,如果缓冲区已满,则等待。removeElement
方法用于从缓冲区移除元素,如果缓冲区为空,则等待。这种同步机制确保了在生产者和消费者之间进行有效的缓冲。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。