답변:
Java 언어 및 런타임에는 기존 구현이 없습니다. 모든 큐는 AbstractQueue를 확장 하고 문서는 전체 큐에 요소를 추가하는 것이 항상 예외로 끝나는 것으로 명확하게 설명합니다. 필요한 기능을 갖추기 위해 대기열을 자신의 클래스로 포장하는 것이 가장 쉽고 간단합니다.
다시 한 번, 모든 큐는 AbstractQueue의 자식이므로 간단히이를 내부 데이터 유형으로 사용하면 사실상 짧은 시간 내에 유연한 구현을 수행해야합니다. :-)
최신 정보:
아래에 설명 된 것처럼 두 가지 공개 구현이 가능합니다 (이 답변은 상당히 오래되었습니다!) . 자세한 내용 은 이 답변 을 참조하십시오.
collection.deque
함께를 사용할 수 있습니다 maxlen
.
실제로 LinkedHashMap 은 원하는 것을 정확하게 수행합니다. removeEldestEntry
메소드 를 대체해야합니다 .
요소가 최대 10 개인 큐의 예 :
queue = new LinkedHashMap<Integer, String>()
{
@Override
protected boolean removeEldestEntry(Map.Entry<Integer, String> eldest)
{
return this.size() > 10;
}
};
"removeEldestEntry"가 true를 리턴하면 가장 큰 항목이 맵에서 제거됩니다.
에서 내 자신의 중복 된 질문 에 이 정답 , 나는이 알게 :
나는 구아바를 생산적으로 사용하고 EvictingQueue
잘 작동했습니다.
인스턴스화하기 위해 EvictingQueue
호출을 정적 팩토리 메소드를 create
및 최대 크기를 지정합니다.
EvictingQueue< Person > people = com.google.common.collect.EvictingQueue.create( 100 ) ; // Set maximum size to 100.
CircularFifoQueue
링크는 죽은 사용하는 대신입니다 commons.apache.org/proper/commons-collections/apidocs/org/...
방금 고정 크기 대기열을 다음과 같이 구현했습니다.
public class LimitedSizeQueue<K> extends ArrayList<K> {
private int maxSize;
public LimitedSizeQueue(int size){
this.maxSize = size;
}
public boolean add(K k){
boolean r = super.add(k);
if (size() > maxSize){
removeRange(0, size() - maxSize);
}
return r;
}
public K getYoungest() {
return get(size() - 1);
}
public K getOldest() {
return get(0);
}
}
removeRange(0, size() - maxSize)
이것은 내가 Queue
래핑 LinkedList
한 것입니다. 여기서 고정 된 크기는 2입니다.
public static Queue<String> pageQueue;
pageQueue = new LinkedList<String>(){
private static final long serialVersionUID = -6707803882461262867L;
public boolean add(String object) {
boolean result;
if(this.size() < 2)
result = super.add(object);
else
{
super.removeFirst();
result = super.add(object);
}
return result;
}
};
....
TMarket.pageQueue.add("ScreenOne");
....
TMarket.pageQueue.add("ScreenTwo");
.....
이 클래스는 상속 대신 컴포지션을 사용하여 작업을 수행합니다 (여기의 답변은 여기에 있습니다). 기본 LinkedList의 트리밍은 add, addAll 및 offer 메소드에서 발생합니다.
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
public class LimitedQueue<T> implements Queue<T>, Iterable<T> {
private final int limit;
private final LinkedList<T> list = new LinkedList<T>();
public LimitedQueue(int limit) {
this.limit = limit;
}
private boolean trim() {
boolean changed = list.size() > limit;
while (list.size() > limit) {
list.remove();
}
return changed;
}
@Override
public boolean add(T o) {
boolean changed = list.add(o);
boolean trimmed = trim();
return changed || trimmed;
}
@Override
public int size() {
return list.size();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public boolean contains(Object o) {
return list.contains(o);
}
@Override
public Iterator<T> iterator() {
return list.iterator();
}
@Override
public Object[] toArray() {
return list.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return list.toArray(a);
}
@Override
public boolean remove(Object o) {
return list.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return list.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends T> c) {
boolean changed = list.addAll(c);
boolean trimmed = trim();
return changed || trimmed;
}
@Override
public boolean removeAll(Collection<?> c) {
return list.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return list.retainAll(c);
}
@Override
public void clear() {
list.clear();
}
@Override
public boolean offer(T e) {
boolean changed = list.offer(e);
boolean trimmed = trim();
return changed || trimmed;
}
@Override
public T remove() {
return list.remove();
}
@Override
public T poll() {
return list.poll();
}
@Override
public T element() {
return list.element();
}
@Override
public T peek() {
return list.peek();
}
}
public class CircularQueue<E> extends LinkedList<E> {
private int capacity = 10;
public CircularQueue(int capacity){
this.capacity = capacity;
}
@Override
public boolean add(E e) {
if(size() >= capacity)
removeFirst();
return super.add(e);
}
}
사용 및 테스트 결과 :
public static void main(String[] args) {
CircularQueue<String> queue = new CircularQueue<>(3);
queue.add("a");
queue.add("b");
queue.add("c");
System.out.println(queue.toString()); //[a, b, c]
String first = queue.pollFirst(); //a
System.out.println(queue.toString()); //[b,c]
queue.add("d");
queue.add("e");
queue.add("f");
System.out.println(queue.toString()); //[d, e, f]
}
add 메소드에 목록이 너무 길면 목록을 자르는 추가 스 니펫이 포함 된 일반 목록처럼 들립니다.
그것이 너무 단순하다면, 아마도 문제 설명을 편집해야 할 것입니다.
또한 이 SO question 또는 ArrayBlockingQueue를 참조하십시오 (차단에주의하십시오.이 경우 원치 않을 수 있습니다).
이 질문을하게 된 요구 사항은 확실하지 않습니다. 고정 된 크기의 데이터 구조가 필요한 경우 다른 캐싱 정책을 살펴볼 수도 있습니다. 그러나 대기열이 있기 때문에 가장 좋은 추측은 일종의 라우터 기능을 찾고 있다는 것입니다. 이 경우 링 버퍼 (첫 번째 인덱스와 마지막 인덱스가있는 배열)를 사용합니다. 요소가 추가 될 때마다 마지막 요소 색인을 증가시키고 요소가 제거 될 때 첫 번째 요소 색인을 증가시킵니다. 두 경우 모두 배열 크기를 모듈로 추가하고 필요할 때, 즉 큐가 가득 찼거나 비어있는 경우 다른 인덱스를 증가시켜야합니다.
또한 라우터 유형의 응용 프로그램 인 경우 랜덤 조기 삭제 (RED)와 같은 알고리즘을 사용하여 큐에서 요소를 채우기 전에 무작위로 요소를 삭제하는 방법을 실험 할 수도 있습니다. 경우에 따라 RED는 삭제 전에 대기열을 채우는 간단한 방법보다 전반적인 성능이 더 우수한 것으로 나타났습니다.
가장 일치하는 답변은 이 다른 질문 에서 나온 것 같습니다. .
Apache Commons Collections 4에는 찾고 있는 CircularFifoQueue 가 있습니다. javadoc 인용 :
CircularFifoQueue는 고정 된 크기의 선입 선출 대기열로, 가장 오래된 요소가 가득 찬 경우이를 대체합니다.
아래의 간단한 해결책은 "문자열"의 대기열입니다.
LinkedHashMap<Integer, String> queue;
int queueKeysCounter;
queue.put(queueKeysCounter++, "My String");
queueKeysCounter %= QUEUE_SIZE;
이렇게하면 대기열에있는 항목의 순서는 유지되지 않지만 가장 오래된 항목은 교체됩니다.
OOP에서 권고 한 바와 같이 상속보다 컴포지션을 선호해야합니다.
여기 내 솔루션은 그것을 염두에두고 있습니다.
package com.choiceview;
import java.util.ArrayDeque;
class Ideone {
public static void main(String[] args) {
LimitedArrayDeque<Integer> q = new LimitedArrayDeque<>(3);
q.add(1);
q.add(2);
q.add(3);
System.out.println(q);
q.add(4);
// First entry ie 1 got pushed out
System.out.println(q);
}
}
class LimitedArrayDeque<T> {
private int maxSize;
private ArrayDeque<T> queue;
private LimitedArrayDeque() {
}
public LimitedArrayDeque(int maxSize) {
this.maxSize = maxSize;
queue = new ArrayDeque<T>(maxSize);
}
public void add(T t) {
if (queue.size() == maxSize) {
queue.removeFirst();
}
queue.add(t);
}
public boolean remove(T t) {
return queue.remove(t);
}
public boolean contains(T t) {
return queue.contains(t);
}
@Override
public String toString() {
return queue.toString();
}
}