क्या एक निश्चित आकार की कतार है जो अत्यधिक तत्वों को निकालती है?


127

मुझे एक निश्चित आकार के साथ एक कतार की आवश्यकता है। जब मैं एक तत्व जोड़ता हूं और कतार भरी होती है, तो यह स्वचालित रूप से सबसे पुराने तत्व को हटा देना चाहिए।

क्या जावा में इसके लिए कोई मौजूदा कार्यान्वयन है?


1
कैसे के बारे में stackoverflow.com/a/6058025/1392882
मिगुएल

जवाबों:


19

जावा भाषा और रनटाइम में कोई मौजूदा कार्यान्वयन नहीं है। सभी क्वीन्स AbstractQueue का विस्तार करते हैं , और इसका डॉक्टर स्पष्ट रूप से कहता है कि एक तत्व को एक पूर्ण कतार में जोड़ना हमेशा एक अपवाद के साथ समाप्त होता है। यह सबसे अच्छा (और काफी सरल) होगा कि आप अपनी जरूरत की कार्यक्षमता के लिए क्यू को अपनी खुद की कक्षा में लपेटें।

एक बार फिर, क्योंकि सभी कतार AbstractQueue के बच्चे हैं, बस इसे अपने आंतरिक डेटा प्रकार के रूप में उपयोग करें और आपके पास एक लचीला कार्यान्वयन होना चाहिए वस्तुतः कुछ ही समय में चल रहा है :-)

अपडेट करें:

जैसा कि नीचे उल्लिखित है, दो खुले कार्यान्वयन उपलब्ध हैं (यह उत्तर काफी पुराना है, लोग!), विवरण के लिए इस उत्तर को देखें।


4
AbstractQueue के बजाय कतार का उपयोग करें ... ऐसी कतारें हो सकती हैं जो इंटरफ़ेस को लागू करती हैं लेकिन सार वर्ग का विस्तार नहीं करती हैं।
टोफूबीर

1
पायथन में आप collection.dequeएक निर्दिष्ट के साथ उपयोग कर सकते हैं maxlen
जोनास गॉगर

2
अद्यतन अब ऐसी दो कक्षाएं उपलब्ध हैं। खुद लिखने की जरूरत नहीं। इस पृष्ठ पर मेरा उत्तर देखें ।
बेसिल बॉर्क

108

वास्तव में LinkedHashMap वही करता है जो आप चाहते हैं। आपको ओवरराइड करने की आवश्यकता हैremoveEldestEntry विधि ।

अधिकतम 10 तत्वों वाली कतार के लिए उदाहरण:

  queue = new LinkedHashMap<Integer, String>()
  {
     @Override
     protected boolean removeEldestEntry(Map.Entry<Integer, String> eldest)
     {
        return this.size() > 10;   
     }
  };

यदि "RemoveEldestEntry" सत्य है, तो मैप से सबसे बड़ी प्रविष्टि को हटा दिया जाता है।


7
यह वास्तव में वह नहीं करता है जो एक कतार करता है, मैं नवीनतम को कैसे पुनः प्राप्त कर सकता हूं। वस्तु?
एलेक्स

69

हाँ, दो

से मेरे अपने डुप्लिकेट प्रश्न के साथ इस सही जवाब , मैं दो का पता चला:


मैंने अमरूद का उत्पादक उपयोग किया EvictingQueue किया, अच्छा काम किया।

एक दृष्टांत के लिए EvictingQueueकॉल स्थिर कारखाने विधि createऔर अपने अधिकतम आकार निर्दिष्ट करें।

EvictingQueue< Person > people = com.google.common.collect.EvictingQueue.create( 100 ) ;  // Set maximum size to 100. 

... और यदि आप कॉमन्स कलेक्शन 4.0 का उपयोग नहीं कर सकते हैं तो सर्कुलर फ़िफ़बोफ़र वी 3.0 में सर्कुलर फ़िफ़्यूक्यू के समान प्रतीत होता है।
श्रीधर सरनोबत

CircularFifoQueueलिंक मृत है, इसके बजाय commons.apache.org/proper/commons-collections/apidocs/org/… का
user7294900

@ user7294900 धन्यवाद, लिंक तय। FYI करें, स्टैक ओवरफ्लो आपको इस तरह के संपादन सीधे एक उत्तर के लिए करने के लिए आमंत्रित करता है। कोई भी संपादित कर सकता है, न कि केवल मूल लेखक। स्टैक ओवरफ्लो उस संबंध में विकिपीडिया को अधिक पसंद करने का इरादा है।
बेसिल बोर्क

@BasilBourque हाँ, लेकिन इस तरह के संपादन को मेरे द्वारा तब भी अस्वीकार किया जा सकता है जब लिंक बदलने पर यह एक ग्रे क्षेत्र है
user7294900

18

मैंने अभी एक निश्चित आकार की कतार को इस तरह लागू किया है:

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);
    }
}

1
यह होना चाहिएremoveRange(0, size() - maxSize)
अहमद हेगज़ी

@AhmedHegazy removeRange (0, size () - maxSize - 1) सही है
Ashish Doneriya

मैं ऊपर अमहद से सहमत हूं। निकालें - 1. अन्यथा अधिकतम क्षमता पर आप एक सरणी के साथ समाप्त हो जाएंगे जो अधिकतम 1 है क्योंकि हम 0 के बारे में बात कर रहे हैं। उदाहरण के लिए। यदि अधिकतम आकार = ५० तो एक नई वस्तु को जोड़ने पर मूल पद में रिमेरेंज सूत्र ५१ - ५० - १ - ० (यानी कुछ भी नहीं हटाया जाएगा) होगा।
जिप

8

यह वही है जो मैंने 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");
.....

4

मुझे लगता है कि आप जो वर्णन कर रहे हैं वह एक परिपत्र कतार है। यहाँ एक उदाहरण है और यहाँ एक बेहतर है


4

यह वर्ग वंशानुक्रम (यहां अन्य उत्तरों) के बजाय रचना का उपयोग करके काम करता है जो कुछ साइड-इफेक्ट्स की संभावना को दूर करता है (जैसा कि आवश्यक रूप से जोश बलोच द्वारा आवश्यक जावा में कवर किया गया है)। अंतर्निहित लिंक्डलिस्ट की ट्रिमिंग मेथड ऐड, ऐडऑल और ऑफर पर होती है।

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();
    }
}

3
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]
}

0

एक साधारण सूची की तरह लगता है जहां ऐड विधि में एक अतिरिक्त स्निपेट होता है जो सूची को बहुत लंबा कर देता है।

यदि यह बहुत सरल है, तो आपको संभवतः अपनी समस्या का विवरण संपादित करना होगा।


दरअसल, उसे पहले तत्व (यानी जल्द से जल्द) को हटाना होगा, ट्रंकटिंग अंतिम तत्व को हटा देगा। अभी भी एक लिंक्डलिस्ट के साथ व्यावहारिक है।
MAK


0

यह बिल्कुल स्पष्ट नहीं है कि आपके पास ऐसी कौन सी आवश्यकताएं हैं जिनके कारण आप यह प्रश्न पूछ सकते हैं। यदि आपको एक निश्चित आकार की डेटा संरचना की आवश्यकता है, तो आप विभिन्न कैशिंग नीतियों को भी देखना चाहते हैं। हालाँकि, जब से आपके पास एक कतार है, मेरा सबसे अच्छा अनुमान यह है कि आप किसी प्रकार की राउटर कार्यक्षमता की तलाश कर रहे हैं। उस मामले में, मैं एक रिंग बफर के साथ जाऊंगा: एक ऐसा सरणी जिसमें पहले और अंतिम सूचकांक हैं। जब भी कोई तत्व जोड़ा जाता है, तो आप अंतिम तत्व सूचकांक को बढ़ाते हैं, और जब कोई तत्व हटा दिया जाता है, तो पहले तत्व सूचकांक को बढ़ाते हैं। दोनों ही मामलों में, इसके अलावा सरणी आकार modulo किया जाता है, और जब आवश्यक है, जब कतार पूर्ण या खाली है, तो अन्य सूचकांक को बढ़ाने के लिए सुनिश्चित करें।

इसके अलावा, यदि यह एक राउटर-प्रकार का अनुप्रयोग है, तो आप रैंडम अर्ली ड्रोपिंग (RED) जैसे एल्गोरिथ्म के साथ प्रयोग करना चाह सकते हैं, जो कतार से तत्वों को भरने से पहले ही बेतरतीब ढंग से छोड़ देता है। कुछ मामलों में, RED को छोड़ने से पहले कतार को भरने की अनुमति देने की सरल विधि की तुलना में बेहतर समग्र प्रदर्शन पाया गया है।


0

वास्तव में आप LinkedList के आधार पर अपना खुद का इम्पैक्ट लिख सकते हैं, यह बिल्कुल सीधा है, बस ऐड मेथड को ओवरराइड करें और स्टाफ को करें।


0

मुझे लगता है कि सबसे अच्छा मिलान उत्तर इस अन्य प्रश्न से है

Apache commons collection 4 में एक CircularFifoQueue है जिसे आप ढूंढ रहे हैं। जावदोक का उद्धरण:

CircularFifoQueue एक निश्चित आकार के साथ पहली-पहली पहली कतार में है जो पूर्ण होने पर अपने सबसे पुराने तत्व को बदल देता है।


0

एक सरल समाधान, नीचे "स्ट्रिंग" की एक कतार है

LinkedHashMap<Integer, String> queue;
int queueKeysCounter;

queue.put(queueKeysCounter++, "My String");
queueKeysCounter %= QUEUE_SIZE;

ध्यान दें कि यह कतार में आइटमों के क्रम को बनाए नहीं रखेगा, लेकिन यह सबसे पुरानी प्रविष्टि को बदल देगा।


0

जैसा कि ओओपी में यह सलाह दी जाती है कि हमें इनहेरिटेंस पर रचना पसंद करनी चाहिए

यहाँ मेरा समाधान यह ध्यान में रखते हुए।

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();
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.