Jawaban:
Tidak ada implementasi yang ada di Bahasa Jawa dan Runtime. Semua Antrian memperpanjang AbstractQueue , dan dokumennya dengan jelas menyatakan bahwa menambahkan elemen ke antrian penuh selalu berakhir dengan pengecualian. Akan lebih baik (dan cukup sederhana) untuk membungkus Antrian ke dalam kelas Anda sendiri karena memiliki fungsi yang Anda butuhkan.
Sekali lagi, karena semua antrian adalah anak-anak dari AbstractQueue, cukup gunakan itu sebagai tipe data internal Anda dan Anda harus memiliki implementasi yang fleksibel berjalan dalam waktu yang hampir tidak ada :-)
MEMPERBARUI:
Seperti diuraikan di bawah ini, ada dua implementasi terbuka yang tersedia (jawaban ini cukup tua, kawan!), Lihat jawaban ini untuk perincian.
collection.deque
dengan yang ditentukan maxlen
.
Sebenarnya LinkedHashMap melakukan apa yang Anda inginkan. Anda perlu mengganti removeEldestEntry
metode.
Contoh untuk antrian dengan maksimal 10 elemen:
queue = new LinkedHashMap<Integer, String>()
{
@Override
protected boolean removeEldestEntry(Map.Entry<Integer, String> eldest)
{
return this.size() > 10;
}
};
Jika "removeEldestEntry" mengembalikan true, entri tertua dihapus dari peta.
Dari pertanyaan rangkap saya sendiri dengan jawaban yang benar ini , saya belajar dua:
Saya memanfaatkan Jambu secara produktif EvictingQueue
, bekerja dengan baik.
Untuk membuat instance EvictingQueue
panggilan metode pabrik statis create
dan tentukan ukuran maksimum Anda.
EvictingQueue< Person > people = com.google.common.collect.EvictingQueue.create( 100 ) ; // Set maximum size to 100.
CircularFifoQueue
tautan sudah mati, gunakan sebaliknya commons.apache.org/proper/commons-collections/apidocs/org/…
Saya baru saja menerapkan antrian ukuran tetap dengan cara ini:
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)
Inilah yang saya lakukan dengan Queue
dibungkus LinkedList
, Ini adalah ukuran tetap yang saya berikan di sini adalah 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");
.....
Saya pikir apa yang Anda gambarkan adalah antrian melingkar. Berikut adalah contoh dan di sini adalah lebih baik satu
Kelas ini melakukan pekerjaan menggunakan komposisi alih-alih pewarisan (jawaban lain di sini) yang menghilangkan kemungkinan efek samping tertentu (seperti yang dicakup oleh Josh Bloch di Essential Java). Pemangkasan LinkedList yang mendasari terjadi pada metode add, addAll dan 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);
}
}
Penggunaan dan hasil tes:
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]
}
Kedengarannya seperti Daftar biasa di mana metode add berisi potongan tambahan yang memotong daftar jika terlalu lama.
Jika itu terlalu sederhana, maka Anda mungkin perlu mengedit deskripsi masalah Anda.
Lihat juga pertanyaan SO ini , atau ArrayBlockingQueue (hati-hati tentang pemblokiran, ini mungkin tidak diinginkan dalam kasus Anda).
Tidak jelas persyaratan apa yang Anda miliki yang membuat Anda mengajukan pertanyaan ini. Jika Anda membutuhkan struktur data ukuran tetap, Anda mungkin juga ingin melihat kebijakan caching yang berbeda. Namun, karena Anda memiliki antrian, tebakan terbaik saya adalah Anda mencari beberapa jenis fungsi router. Dalam hal ini, saya akan menggunakan buffer cincin: array yang memiliki indeks pertama dan terakhir. Setiap kali elemen ditambahkan, Anda hanya menambah indeks elemen terakhir, dan ketika elemen dihapus, tambah indeks elemen pertama. Dalam kedua kasus, penambahan dilakukan modulo ukuran array, dan pastikan untuk menambah indeks lain saat diperlukan, yaitu, ketika antrian penuh atau kosong.
Selain itu, jika ini adalah aplikasi tipe router, Anda mungkin juga ingin bereksperimen dengan algoritma seperti Random Early Dropping (RED), yang menjatuhkan elemen dari antrian secara acak bahkan sebelum terisi. Dalam beberapa kasus, RED telah ditemukan memiliki kinerja keseluruhan yang lebih baik daripada metode sederhana yang memungkinkan antrian untuk diisi sebelum jatuh.
Saya pikir jawaban yang paling cocok adalah dari pertanyaan lain ini .
Koleksi Apache commons 4 memiliki CircularFifoQueue yang merupakan apa yang Anda cari. Mengutip javadoc:
CircularFifoQueue adalah antrian masuk pertama keluar dengan ukuran tetap yang menggantikan elemen tertua jika penuh.
Solusi sederhana, di bawah ini adalah Antrian "String"
LinkedHashMap<Integer, String> queue;
int queueKeysCounter;
queue.put(queueKeysCounter++, "My String");
queueKeysCounter %= QUEUE_SIZE;
Perhatikan bahwa ini tidak akan mempertahankan Urutan item dalam Antrian, tetapi itu akan menggantikan entri tertua.
Seperti yang disarankan dalam OOP bahwa kita harus lebih memilih Komposisi daripada Warisan
Di sini solusi saya mengingatnya.
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();
}
}