Collections 在Java中容纳最后N个元素的大小受限队列

Collections 在Java中容纳最后N个元素的大小受限队列,collections,queue,java,Collections,Queue,Java,关于Java库的一个非常简单和快速的问题:是否有一个现成的类实现了一个具有固定最大大小的队列——也就是说,它总是允许添加元素,但它会悄悄地删除head元素以容纳新添加元素的空间 当然,手动实现它很简单: import java.util.LinkedList; public class LimitedQueue<E> extends LinkedList<E> { private int limit; public LimitedQueue(int l

关于Java库的一个非常简单和快速的问题:是否有一个现成的类实现了一个具有固定最大大小的
队列
——也就是说,它总是允许添加元素,但它会悄悄地删除head元素以容纳新添加元素的空间

当然,手动实现它很简单:

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;
    }
}
import java.util.LinkedList;
公共类LimitedQueue扩展了LinkedList{
私有整数限制;
公共限制队列(整数限制){
这个极限=极限;
}
@凌驾
公共布尔加法(EO){
增补(o);
而(size()>limit){super.remove();}
返回true;
}
}

据我所知,Java stdlibs中没有标准的实现,但Apache Commons或类似的东西中可能有标准的实现?

我所知道的唯一空间有限的是BlockingQueue接口(例如,由ArrayBlockingQueue类实现),但如果填充了,它们不会删除第一个元素,而是阻止put操作,直到空间空闲(被其他线程移除)


据我所知,您的简单实现是获得这种行为的最简单方法。

使用composition not extends(是的,我指的是extends,如java中对extends关键字的引用,是的,这是继承)。组合更优越,因为它完全屏蔽了您的实现,允许您在不影响类用户的情况下更改实现

我建议尝试类似的方法(我直接在这个窗口中输入,所以买家要小心语法错误):

public LimitedSizeQueue实现队列
{
私有int-maxSize;
私有链接列表存储区;
公共有限大小(最终整数最大大小)
{
this.maxSize=maxSize;
storageArea=新的LinkedList();
}
公共布尔报价(ElementType元素)
{
if(storageArea.size()
更好的选择(基于Asaf的答案)可能是使用泛型类包装。例如:

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
}
public LimitedSizeQueue实现队列
{
私有int-maxSize;
私人循环费储存区;
公共有限大小(最终整数最大大小)
{
如果(最大尺寸>0)
{
this.maxSize=maxSize;
storateArea=新的循环ifobuffer(最大尺寸);
}
其他的
{
抛出新的IllegalArgumentException(“诸如此类”);
}
}
…使用CircularFifoBuffer类实现队列接口
}
您可以使用来自、来自javadoc的:

可以使用最大大小配置最小-最大优先级队列。如果是这样,每次队列大小超过该值时,队列都会根据其比较器(可能是刚刚添加的元素)自动删除其最大元素。这与传统的有界队列不同,后者在新元素满时阻止或拒绝新元素


Apache commons collections 4有一个您正在寻找的版本。引用javadoc:

CircularFifoQueue是一个具有固定大小的先进先出队列,如果已满,它将替换其最早的元素

import java.util.Queue;
导入org.apache.commons.collections4.queue.CircularFifoQueue;
队列fifo=新循环fifo(2);
先进先出。添加(1);
先进先出。添加(2);
先进先出。添加(3);
系统输出打印LN(fifo);
//观察结果:
// [2, 3]
如果您使用的是较旧版本的ApacheCommons集合(3.x),则可以使用,这与没有泛型的情况基本相同


更新:在支持泛型的commons collections第4版发布后更新了答案。

LRUMap是另一种可能性,同样来自Apache commons


我喜欢@FractalizeR solution。但是我会保留并返回super.add(o)中的值

public class LimitedQueue扩展LinkedList{
私有整数限制;
公共限制队列(整数限制){
这个极限=极限;
}
@凌驾
公共布尔加法(EO){
布尔加法=超级加法(o);
while(添加了&&size()>限制){
super.remove();
}
增加了退货;
}
}
Guava现在有一个非阻塞队列,当试图向队列中添加新元素时,该队列会自动从队列的头部逐出元素,并且队列已满

import java.util.Queue;
导入com.google.common.collect.executingqueue;
队列fifo=退出队列。创建(2);
先进先出。添加(1);
先进先出。添加(2);
先进先出。添加(3);
系统输出打印LN(fifo);
//观察结果:
// [2, 3]
公共类ArrayLimitedQueue扩展了ArrayQueue{
私有整数限制;
公共ArrayLimitedQueue(整数限制){
超级(限制+1);
这个极限=极限;
}
@凌驾
公共布尔加法(EO){
布尔加法=超级加法(o);
while(添加了&&size()>限制){
super.remove();
}
增加了退货;
}
@凌驾
公共无效地址(E){
super.addLast(e);
while(size()>限制){
super.removeLast();
}
}
@凌驾
公共布尔offerLast(E){
布尔加法=super.offerLast(e);
while(添加了&&size()>限制){
super.pollLast();
}
增加了退货;
}
}

好的,我将分享这个选项。这是一个性能非常好的选项—它在内部使用数组—并重用条目。它是线程安全的—您可以将内容作为列表检索

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
    }
}
静态类FixedSizeCircularReference{
T[]项
FixedSizeCircularReference(整数大小){
this.entries=新对象[大小]为T[]
this.size=size
}
int cur=0
整数大小
同步v
    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]
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;
    }
}
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]
    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;
    }
}
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
    }
}