Collections 在Java中容纳最后N个元素的大小受限队列
关于Java库的一个非常简单和快速的问题:是否有一个现成的类实现了一个具有固定最大大小的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
队列
——也就是说,它总是允许添加元素,但它会悄悄地删除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
}
}