1. 概述

本文我们将学习了解 Apache Commons Collections中提供的 CircularFifoQueue 数据结构。

CircularFifoQueue 实现了 Queue 接口, 是一个 固定大小, 非阻塞队列当插入元素队列已满时,最旧的元素将被删除以为新元素腾出空间.

2. Maven 依赖

首先添加Maven依赖

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.1</version>
</dependency>

最新版本请查看 Maven 仓库.

3. 初始化-构造函数

使用默认构造函数,它创建一个默认大小为 32 的队列

CircularFifoQueue<String> bits = new CircularFifoQueue();

也可指定队列所需的最大大小:

CircularFifoQueue<String> colors = new CircularFifoQueue<>(5);

另外也可接受Collection作为构造函数参数来创建 CircularFifoQueue 对象。这种情况,队列将填充Collection的元素,并且其大小与集合的大小相同:

CircularFifoQueue<String> daysOfWeek = new CircularFifoQueue<>(days);

注意:由于这个队列在构造时已经满了,任何新增都会导致第一个创建的元素被丢弃。

4. 添加元素

与其他 Queue 接口实现一样,我们可以使用 add 和 offer 方法添加元素。Queue JavaDoc 指出 offer 方法应在操作容量限制的队列时使用。

然而,由于 CircularFifoQueue 是非阻塞的,插入操作不会失败。因此,它的 addoffer 方法表现出相同的行为。

让我们看看如何使用 add 方法向我们的 colors 队列添加元素:

colors.add("Red");
colors.add("Blue");
colors.add("Green");

以及如何使用 offer 添加:

colors.offer("White");
colors.offer("Black");

5. 查找和删除元素

5.1. Peek 方法

peek 返回队列的第一个元素。

只要在调用之间没有更改队列中的元素,此方法将始终返回相同的元素。如果队列为空,则 peek 方法将返回 null

String colorsHead = colors.peek();

5.2. Element 方法

element 方法类似于 peek,区别是如果队列为空会抛出异常:

colorsHead = colors.element();

5.3. Get 方法

使用 get 方法传入索引,获取队列中指定位置元素:

String color = colors.get(1);

上面会返回 “Blue“。

现在让我们向队列中再添加三个元素,并再次检查这个结果:

colors.add("Orange");
colors.add("Violet");
colors.add("Pink");

color = colors.get(1);

这次,get 方法返回 "Black"。因为我们的队列大小限制为5,插入新元素时,前三个元素("Red"、"Blue"、"Green")被删除。

5.4. Poll 方法

poll 方法会移除队首元素并返回该元素。如果队列没有元素,则 poll 方法返回 null:

colorsHead = colors.poll();

5.5. Remove 方法

remove 方法与 poll 方法类似,它返回队列的头部元素并将返回的元素从队列中移除。但是,如果队列为空,remove 方法将抛出异常

colorsHead = colors.remove();

5.6. Clear 方法

用于清空队列

colors.clear();

6. 状态检测

maxSize 方法返回队列的最大容量

int maxSize = bits.maxSize();

这里会返回 32,因为示例中的 bits 队列是使用默认构造函数创建的。

size 方法返回队列中实际元素数量:

int size = colors.size();

isEmpty 检查队列是否为空:

boolean isEmpty = bits.isEmpty();

isAtFullCapacity 检查队列是否已满:

boolean isFull = daysOfWeek.isAtFullCapacity();

需要注意的是,此方法仅在 4.1 版本及以上可用。

另一个我们可以用来检测队列是否已满的方法是 isFull 。但对于 CircularFifoQueue,isFull 方法将始终返回 false,因为队列始终可以接受新元素:

boolean isFull = daysOfWeek.isFull();

7. 总结

本文介绍了如何使用 Apache Commons 的 CircularFifoQueue。我们看了一些示例,说明了如何实例化队列对象、填充队列、清空队列、获取和删除队列中的元素以及检查队列的大小和容量。

最后完整代码可从 GitHub 上获取。