queue 队列测试

队列是一种遵循先进先出原则的数据结构,常见实现包括循环数组的ArrayDeque和链表的LinkedList。ArrayDeque在效率上优于LinkedList,但可能会受到容量限制。在多线程场景中,阻塞队列如java.util.concurrent包中的队列能实现线程间的负载平衡。队列接口提供了add、remove、element等方法,不同的操作在队列满或空时有不同的处理策略,如阻塞或返回特殊值。

队列接口指出可以在队列的尾部添加元素,在队列的头部删除元素,并且可以查找队列中元素的个数。当需要收集队列,并按照”先进先出”的规则检索对象时就应该使用队列。

队列实现方式,通常有两种方式:一种是使用循环数组;另一种是使用链表。每个实现都可以通过一个实现了Queue接口的类表示。如果需要一个循环数组队列,就可以使用ArrayDeque类,如果需要一个链表队列,就直接使用LinkedList类。

实现方式的效率,循环数组要比链表更高效,因此多数人优先选择循环数组,然而,通常这样做也需要付出一定的代价。

循环数组是一个有界集合,即容量有限。如果程序中要搜集的对象数量没有上限,就最好使用链表来实现。

代码块

package yu.bai.collection;

import org.junit.Test;

import java.util.LinkedList;
import java.util.Queue;

import org.junit.Before;

/**
 * 队列测试:实现类使用LinkedList
 */
public class TestQuene {

    // 定义一个队列
    Queue<String> queue;

    @Before
    public void before() {
        // 实例化队列变量
        queue = new LinkedList<String>();

        // add方法向队列中添加元素,返回布尔值,add方法添加失败时会抛异常,不推荐使用
        // queue.add("1");
        // queue.add("2");
        // queue.add("3");
        // queue.add("4");
        // queue.add("5");

        // offer方法向队列中添加元素,返回布尔值
        queue.offer("a");
        queue.offer("b");
        queue.offer("c");
        queue.offer("d");
        queue.offer("e");

    }

    // poll方法移除队列首个元素并返回,若队列为空,返回null
    @Test
    public void test1() {
        // 弹出元素
        String pollEle = queue.poll(); // 先进先出,弹出了a
        System.out.println(pollEle); // a
        System.out.println(queue); // [b, c, d, e]
    }

    // remove方法移除首个元素并返回,若队列为空,会抛出异常:NoSuchElementException,不推荐使用
    @Test
    public void test2() {
        // 弹出元素
        String remove = queue.remove(); // 先进先出,弹出了a
        System.out.println(remove); // a
        System.out.println(queue); // [b, c, d, e]
    }

    // peek方法返回队列首个元素,但不移除,若队列为空,返回null
    @Test
    public void test3() {
        // 查看首个元素
        String peek = queue.peek(); // 首个元素是a,最先加入
        System.out.println(peek); // a
        System.out.println(queue); // [a, b, c, d, e]
    }

    // element方法返回队列的头元素,但不移除,若队列为空,会抛出异常:NoSuchElementException,不推荐使用
    @Test
    public void test4() {
        // 查看首个元素
        String element = queue.element();
        System.out.println(element); // a
        System.out.println(queue); // [a, b, c, d, e]
    }
}
  1. 每个方法都存在两种形式:一种抛出异常(操作失败时),另一种返回一个特殊值(null或false,具体取决于操作)。
  2. 队列是一种数据结构.它有两个基本操作:在队列尾部加人一个元素,和从队列头部移除一个元素就是说,队列以一种先进先出的方式管理数据,如果你试图向一个已经满了的阻塞队列中添加一个元素或者是从一个空的阻塞队列中移除一个元索,将导致线程阻塞.在多线程进行合作时,阻塞队列是很有用的工具。工作者线程可以定期地把中间结果存到阻塞队列中而其他工作者线线程把中间结果取出并在将来修改它们。队列会自动平衡负载。如果第一个线程集运行得比第二个慢,则第二个线程集在等待结果时就会阻塞。如果第一个线程集运行得快,那么它将等待第二个线程集赶上来。下表显示了jdk1.5中的阻塞队列的操作:
    add 增加一个元索 如果队列已满,则抛出一个IIIegaISlabEepeplian异常

    remove 移除并返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常

    element 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常

    offer 添加一个元素并返回true 如果队列已满,则返回false

    poll 移除并返问队列头部的元素 如果队列为空,则返回null

    peek 返回队列头部的元素 如果队列为空,则返回null

    put 添加一个元素 如果队列满,则阻塞

    take 移除并返回队列头部的元素 如果队列为空,则阻塞

    remove、element、offer 、poll、peek 其实是属于Queue接口。

### 如何遍历 `queue` 队列 对于不同编程语言中的队列,遍历方式有所不同。以下是几种常见的方式。 #### Java 中的 Queue 遍历 Java 提供了多种方法来遍历 `Queue` 接口及其子类的对象。下面展示了一种常见的做法: ```java import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("First"); queue.offer("Second"); queue.offer("Third"); while (!queue.isEmpty()) { System.out.println(queue.poll()); // 使用poll移除并打印头元素直到队列为空 } } } ``` 另一种更现代的方法是使用增强型for循环或流操作来进行遍历[^5]: ```java import java.util.ArrayDeque; import java.util.Deque; import java.util.stream.StreamSupport; public class StreamExample { public static void main(String[] args) { Deque<Integer> deque = new ArrayDeque<>(List.of(1, 2, 3)); // 将deque转换成stream再进行处理 StreamSupport.stream(deque.spliterator(), false).forEach(System.out::println); } } ``` 这里需要注意的是,在某些情况下可能不希望破坏原始队列的内容;此时应考虑复制一份副本用于迭代访问或是采用其他非破坏性的读取手段。 #### C++ STL 中的 queue 遍历 由于C++标准库中的`std::queue`并不支持随机访问其内部存储的数据项,因此要实现遍历通常有两种思路:一是通过不断调用成员函数`front()`获取最前面的一个元素后再配合`pop()`将其弹出从而完成逐一遍历;二是借助辅助容器暂存待处理节点以便后续恢复原状[^1]。 下面是第一种方案的具体实现例子: ```cpp #include <iostream> #include <queue> int main(){ std::queue<int> q; for(int i=0;i<5;++i){ q.push(i*2); // 向队列中加入一些整数作为测试数据 } while(!q.empty()){ int frontElement=q.front(); // 获取当前队首元素 std::cout<<frontElement<<"\n"; q.pop(); // 删除已处理过的队首元素 } return 0; } ``` 第二种情况则适用于那些不允许改变原有队列状态的应用场景下,比如当需要多次重复执行相同模式下的遍历时就可以采取这种方式。 #### Python 中的 queue 模块 Python内置模块`queue`提供了线程安全版本的各种类型的队列对象。为了能够方便地对其进行遍历,一般会结合条件变量或其他同步机制确保多线程环境下的一致性和安全性[^4]。 简单来说就是创建一个新的列表用来保存所有的元素然后再逐一输出它们即可: ```python from queue import Queue def traverse_queue(q): result = [] temp_q = Queue() while not q.empty(): item = q.get() # 取得下一个项目而不删除它 result.append(item) temp_q.put(item) # 把临时队列里的东西放回原来的队列里去保持不变的状态 while not temp_q.empty(): q.put(temp_q.get()) return result if __name__ == '__main__': testQ = Queue() items_to_add=[str(x)+"_item" for x in range(5)] for itm in items_to_add: testQ.put(itm) traversed_items=traverse_queue(testQ) print(traversed_items) ``` 此段代码展示了如何在不影响实际队列内容的前提下对其内含有的各个条目实施遍历动作。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值