非常简单&关于Java库的快速问题:是否有一个现成的类,它实现了一个具有固定最大大小的Queue
- 即它总是允许添加元素,但它会默默地删除头元素以容纳新添加元素的空间。
当然,手动实施它是微不足道的:
import java.util.LinkedList;
public class LimitedQueue<E> extends LinkedList<E> {
private int limit;
public LimitedQueue(int limit) {
this.limit = limit;
}
@Override
public boolean add(E o) {
super.add(o);
while (size() > limit) { super.remove(); }
return true;
}
}
据我所知,Java stdlibs中没有标准实现,但可能是Apache Commons中的那个或类似的东西?
答案 0 :(得分:152)
Apache commons集合4有CircularFifoQueue<>这就是你要找的东西。引用javadoc:
CircularFifoQueue是一个先进先出队列,具有固定大小,如果已满,则替换其最旧的元素。
import java.util.Queue;
import org.apache.commons.collections4.queue.CircularFifoQueue;
Queue<Integer> fifo = new CircularFifoQueue<Integer>(2);
fifo.add(1);
fifo.add(2);
fifo.add(3);
System.out.println(fifo);
// Observe the result:
// [2, 3]
如果您使用的是较旧版本的Apache commons集合(3.x),则可以使用CircularFifoBuffer,这与没有泛型的情况基本相同。
更新:在支持泛型的commons集合版本4发布后更新的答案。
答案 1 :(得分:82)
Guava现在有一个EvictingQueue,一个非阻塞队列,当尝试将新元素添加到队列中并且它已满时,它会自动驱逐队列头部的元素。 < / p>
import java.util.Queue;
import com.google.common.collect.EvictingQueue;
Queue<Integer> fifo = EvictingQueue.create(2);
fifo.add(1);
fifo.add(2);
fifo.add(3);
System.out.println(fifo);
// Observe the result:
// [2, 3]
答案 2 :(得分:11)
我喜欢@FractalizeR解决方案。但我还要保留并返回super.add(o)中的值!
public class LimitedQueue<E> extends LinkedList<E> {
private int limit;
public LimitedQueue(int limit) {
this.limit = limit;
}
@Override
public boolean add(E o) {
boolean added = super.add(o);
while (added && size() > limit) {
super.remove();
}
return added;
}
}
答案 3 :(得分:5)
使用composition not extends(是的,我的意思是扩展,就像在java中对extends关键字的引用一样,是的,这是继承)。组合更加超级,因为它完全屏蔽了您的实现,允许您更改实现而不会影响您的类的用户。
我建议尝试这样的事情(我直接在这个窗口中打字,所以买家要小心语法错误):
public LimitedSizeQueue implements Queue
{
private int maxSize;
private LinkedList storageArea;
public LimitedSizeQueue(final int maxSize)
{
this.maxSize = maxSize;
storageArea = new LinkedList();
}
public boolean offer(ElementType element)
{
if (storageArea.size() < maxSize)
{
storageArea.addFirst(element);
}
else
{
... remove last element;
storageArea.addFirst(element);
}
}
... the rest of this class
更好的选择(基于Asaf的答案)可能是用Apache Collections CircularFifoBuffer包含泛型类。例如:
public LimitedSizeQueue<ElementType> implements Queue<ElementType>
{
private int maxSize;
private CircularFifoBuffer storageArea;
public LimitedSizeQueue(final int maxSize)
{
if (maxSize > 0)
{
this.maxSize = maxSize;
storateArea = new CircularFifoBuffer(maxSize);
}
else
{
throw new IllegalArgumentException("blah blah blah");
}
}
... implement the Queue interface using the CircularFifoBuffer class
}
答案 4 :(得分:4)
我唯一知道空间有限的是BlockingQueue接口(例如由ArrayBlockingQueue类实现) - 但它们不会删除第一个元素(如果填充),而是阻止put操作直到空间空闲(删除)通过其他线程)。
据我所知,您的琐碎实施是获得此类行为的最简单方法。
答案 5 :(得分:3)
LRUMap是另一种可能性,也来自Apache Commons。
http://commons.apache.org/collections/apidocs/org/apache/commons/collections/map/LRUMap.html
答案 6 :(得分:2)
您可以使用来自MinMaxPriorityQueue的Google Guava来自javadoc:
可以使用最大大小配置最小 - 最大优先级队列。如果是这样,每次队列的大小超过该值时,队列将根据其比较器(可能是刚刚添加的元素)自动删除其最大元素。这与传统的有界队列不同,传统的有界队列在满员时阻止或拒绝新元素。
答案 7 :(得分:0)
好的,我将分享此选项。这是一个非常不错的选择-内部使用数组-并重用条目。这是线程安全的-您可以将内容作为列表检索。
static class FixedSizeCircularReference<T> {
T[] entries
FixedSizeCircularReference(int size) {
this.entries = new Object[size] as T[]
this.size = size
}
int cur = 0
int size
synchronized void add(T entry) {
entries[cur++] = entry
if (cur >= size) {
cur = 0
}
}
List<T> asList() {
int c = cur
int s = size
T[] e = entries.collect() as T[]
List<T> list = new ArrayList<>()
int oldest = (c == s - 1) ? 0 : c
for (int i = 0; i < e.length; i++) {
def entry = e[oldest + i < s ? oldest + i : oldest + i - s]
if (entry) list.add(entry)
}
return list
}
}
答案 8 :(得分:-1)
public class ArrayLimitedQueue<E> extends ArrayDeque<E> {
private int limit;
public ArrayLimitedQueue(int limit) {
super(limit + 1);
this.limit = limit;
}
@Override
public boolean add(E o) {
boolean added = super.add(o);
while (added && size() > limit) {
super.remove();
}
return added;
}
@Override
public void addLast(E e) {
super.addLast(e);
while (size() > limit) {
super.removeLast();
}
}
@Override
public boolean offerLast(E e) {
boolean added = super.offerLast(e);
while (added && size() > limit) {
super.pollLast();
}
return added;
}
}