2011-09-01 14 views
63

मेरे पास स्ट्रीमिंग समय श्रृंखला है, जिसमें से मुझे पिछले 4 तत्वों को रखने में दिलचस्पी है, जिसका अर्थ है कि मैं पहले पॉप करने में सक्षम होना चाहता हूं, और अंत में जोड़ना चाहता हूं। इसके लिए कौन सा जावा संग्रह सबसे अच्छा है? वेक्टर ?जावा - रिंग बफर

+1

'LinkedList' हे (1) आवेषण और हटा देगा के लिए एक उचित विकल्प की तरह लगता है, आप हे (1) अनुक्रमण की जरूरत है,:

यहाँ देखें? –

+3

थ्रेड सुरक्षित? धागा सुरक्षित नहीं है? अंत से हटाने और शुरुआत में जोड़ने के लिए आमतौर पर एक लिंक्डलिस्ट आमतौर पर सबसे अच्छा विकल्प होता है। –

+0

यह भी देखें [कैसे-आप-कोड-एक-कुशल-परिपत्र-बफर-इन-जावा-या-सी-तेज?] (Http://stackoverflow.com/questions/590069/how-would-you- कोड-ए-कुशल-सर्कुलर-बफर-इन-जावा-या-सी-तेज? lq = 1) – nawfal

उत्तर

-2

उपयोग एक Queue

Queue<String> qe=new LinkedList<String>(); 

qe.add("a"); 
qe.add("b"); 
qe.add("c"); 
qe.add("d"); 

System.out.println(qe.poll()); //returns a 
System.out.println(qe.poll()); //returns b 
System.out.println(qe.poll()); //returns c 
System.out.println(qe.poll()); //returns d 

वहाँ एक Queue

  • तत्व() के पांच सरल तरीके है - प्राप्त करता है, लेकिन दूर नहीं करता, इस कतार के सिर।

  • ऑफ़र (ई ओ) -
    संभव होने पर निर्दिष्ट कतार में निर्दिष्ट तत्व डालें।

  • peek() - इस 0eकतार के सिर को पुनर्प्राप्त करता है, लेकिन हटा नहीं जाता है, अगर यह कतार खाली है तो शून्य वापस लौटाएं।

  • मतदान() - इस कतार के खाली होने पर शून्य को पुनर्प्राप्त और हटा देता है।

  • हटाएं() - इस कतार के सिर को पुनर्प्राप्त और हटा देता है।
+15

यह सभी तत्वों को रखता है, न केवल अंतिम 4 – dkneller

77

अपाचे Common.Collections से CircularFifoBuffer पर विचार करें। Queue के विपरीत आपको अंतर्निहित संग्रह के सीमित आकार को बनाए रखने की आवश्यकता नहीं है और सीमा पार करने के बाद इसे लपेटें।

Buffer buf = new CircularFifoBuffer(4); 
buf.add("A"); 
buf.add("B"); 
buf.add("C"); 
buf.add("D"); //ABCD 
buf.add("E"); //BCDE 

CircularFifoBuffer क्योंकि निम्नलिखित गुण की आपके लिए यह कर देगा:

  • CircularFifoBuffer एक एक निश्चित आकार कि यदि पूर्ण यहां का सबसे पुराना तत्व की जगह के साथ पहली बार बाहर बफर में पहला है।
  • परिपत्रफिफ़ोफर का निष्कासन आदेश सम्मिलन आदेश पर आधारित है; तत्वों को उसी क्रम में हटा दिया जाता है जिसमें वे जोड़े गए थे। पुनरावृत्ति आदेश हटाने के आदेश के समान है।
  • ऐड (ऑब्जेक्ट), BoundedFifoBuffer.remove() और BoundedFifoBuffer.get() ऑपरेशंस सभी स्थिर समय में प्रदर्शन करते हैं। अन्य सभी परिचालन रैखिक समय या बदतर में प्रदर्शन करते हैं।

हालांकि आपको इसकी सीमाओं पर भी विचार करना चाहिए - उदाहरण के लिए, आप इस संग्रह में गायब टाइमरीज़ नहीं जोड़ सकते हैं क्योंकि यह नल की अनुमति नहीं देता है।

+2

मूल कॉमन्स संग्रह से प्राप्त संस्करण बनता है जेनेरिक का उपयोग करता है: http://sourceforge.net/projects/collections/ (ऐसा लगता है कि प्रोजेक्ट को जिथब में ले जाया गया था) –

+2

कॉमन्स कलेक्शन 4.0 में [सर्कुलरफिफो क्यूयू] शामिल है (http://commons.apache.org/proper/commons -कोलेक्शन/जावाडॉक्स/एपीआई-रिलीज/ऑर्ग/अपाचे/कॉमन्स/कलेक्शन 4/कतार/सर्कुलरफिफो क्यूयूयू.html) जिसमें समान गुण हैं, और जेनेरिक का समर्थन करते हैं। – Pete

+0

मैंने देखा कि CircularFifoQueue इस तरह काम नहीं करता है। जब मैं "हेल्लो" को 3 इकाई आकार के कतार में डालता हूं, तो मैं "एचईएल" से "एलईएल" से "एलओएल" तक जाता हूं। @AndryTaptunov द्वारा वर्णित सुविधा के साथ क्या हुआ? –

5

मुझे कुछ समय पहले एक ही समस्या थी और निराश था क्योंकि मुझे कोई समाधान नहीं मिला जो मेरी ज़रूरतों को सुइट करता है इसलिए मैंने अपनी कक्षा लिखी। ईमानदारी से, मुझे कुछ कोड वापस मिला, लेकिन वह भी नहीं था जिसे मैं खोज रहा था इसलिए मैंने इसे अनुकूलित किया और अब मैं इसे साझा कर रहा हूं, जैसे कोड के उस टुकड़े के लेखक की तरह।

संपादित करें: यह मूल (हालांकि थोड़ा अलग) कोड है: CircularArrayList for java

क्योंकि यह समय पहले किया गया था मैं स्रोत का लिंक नहीं है, लेकिन यहाँ कोड है:

import java.util.AbstractList; 
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List; 
import java.util.RandomAccess; 

public class CircularArrayList<E> extends AbstractList<E> implements RandomAccess { 

private final int n; // buffer length 
private final List<E> buf; // a List implementing RandomAccess 
private int leader = 0; 
private int size = 0; 


public CircularArrayList(int capacity) { 
    n = capacity + 1; 
    buf = new ArrayList<E>(Collections.nCopies(n, (E) null)); 
} 

public int capacity() { 
    return n - 1; 
} 

private int wrapIndex(int i) { 
    int m = i % n; 
    if (m < 0) { // modulus can be negative 
     m += n; 
    } 
    return m; 
} 

@Override 
public int size() { 
    return this.size; 
} 

@Override 
public E get(int i) { 
    if (i < 0 || i >= n-1) throw new IndexOutOfBoundsException(); 

    if(i > size()) throw new NullPointerException("Index is greater than size."); 

    return buf.get(wrapIndex(leader + i)); 
} 

@Override 
public E set(int i, E e) { 
    if (i < 0 || i >= n-1) { 
     throw new IndexOutOfBoundsException(); 
    } 
    if(i == size()) // assume leader's position as invalid (should use insert(e)) 
     throw new IndexOutOfBoundsException("The size of the list is " + size() + " while the index was " + i 
       +". Please use insert(e) method to fill the list."); 
    return buf.set(wrapIndex(leader - size + i), e); 
} 

public void insert(E e) 
{ 
    int s = size();  
    buf.set(wrapIndex(leader), e); 
    leader = wrapIndex(++leader); 
    buf.set(leader, null); 
    if(s == n-1) 
     return; // we have replaced the eldest element. 
    this.size++; 

} 

@Override 
public void clear() 
{ 
    int cnt = wrapIndex(leader-size()); 
    for(; cnt != leader; cnt = wrapIndex(++cnt)) 
     this.buf.set(cnt, null); 
    this.size = 0;  
} 

public E removeOldest() { 
    int i = wrapIndex(leader+1); 

    for(;;i = wrapIndex(++i)) { 
     if(buf.get(i) != null) break; 
     if(i == leader) 
      throw new IllegalStateException("Cannot remove element." 
        + " CircularArrayList is empty."); 
    } 

    this.size--; 
    return buf.set(i, null); 
} 

@Override 
public String toString() 
{ 
    int i = wrapIndex(leader - size()); 
    StringBuilder str = new StringBuilder(size()); 

    for(; i != leader; i = wrapIndex(++i)){ 
     str.append(buf.get(i)); 
    } 
    return str.toString(); 
} 

public E getOldest(){ 
    int i = wrapIndex(leader+1); 

    for(;;i = wrapIndex(++i)) { 
     if(buf.get(i) != null) break; 
     if(i == leader) 
      throw new IllegalStateException("Cannot remove element." 
        + " CircularArrayList is empty."); 
    } 

    return buf.get(i); 
} 

public E getNewest(){ 
    int i = wrapIndex(leader-1); 
    if(buf.get(i) == null) 
     throw new IndexOutOfBoundsException("Error while retrieving the newest element. The Circular Array list is empty."); 
    return buf.get(i); 
} 
} 
+2

यह वह स्रोत हो सकता है जिसका आप उल्लेख कर रहे हैं: http://www.museful.net/2011/software-development/circulararraylist-for-java –

+0

हां, यह मूल स्रोत है। (अब मैं अपनी पोस्ट संपादित करूंगा।) – vgfeit

+1

मैंने इस कोड को आजमाया। परिपत्रअरेलेलिस्ट buf = नया परिपत्रअरेलेलिस्ट (4); buf.insert ("ए"); buf.insert ("बी"); System.out.println (buf); // [शून्य, शून्य] buf.insert ("सी"); buf.insert ("डी"); System.out.println (buf); // [शून्य, ए, बी, सी] स्ट्रिंग res = buf.get (0); // शून्य पर कोड http://www.museful.net/2011/software-development/circulararraylist-for-java मेरे लिए बेहतर काम करता है। –

10

आप की जरूरत है

  • हे (1) प्रविष्टि और हटाने
  • हे (1) आंतरिक तत्वों को अनुक्रमण
  • किसी एकल थ्रेड केवल
  • सामान्य तत्व प्रकार

तो आप (उदाहरण के लिए) इस तरह से this CircularArrayList for Java उपयोग कर सकते हैं से

  • पहुँच:

    CircularArrayList<String> buf = new CircularArrayList<String>(4); 
    
    buf.add("A"); 
    buf.add("B"); 
    buf.add("C"); 
    buf.add("D"); // ABCD 
    
    String pop = buf.remove(0); // A <- BCD 
    buf.add("E"); // BCDE 
    
    String interiorElement = buf.get(i); 
    

    सभी इन तरीकों हे में चलाने (1)।

  • 11

    जावा 1.6 के बाद से, ArrayDeque है, जो Queue लागू करता है और एक LinkedList तुलना में तेजी से और अधिक स्मृति कुशल हो रहा है और ArrayBlockingQueue का धागा तुल्यकालन भूमि के ऊपर नहीं है: एपीआई डॉक्स से: "यह वर्ग है एक स्टैक के रूप में उपयोग किए जाने पर स्टैक से तेज़ होने की संभावना है, और कतार के रूप में उपयोग किए जाने पर लिंक्डलिस्ट से तेज़ हो सकता है। "

    final Queue<Object> q = new ArrayDeque<Object>(); 
    q.add(new Object()); //insert element 
    q.poll(); //remove element 
    
    +0

    क्या ऐरेडेक थ्रेड-सुरक्षित है? @ टी। बाउम – fjjiaboming

    +0

    यह असहज हो जाता है और रिंग बफर की तरह व्यवहार नहीं करता है। – scorpiodawg

    35

    अमरूद 15.0 के बाद से (सितंबर 2013 को जारी) वहाँ EvictingQueue है:

    एक गैर अवरुद्ध कतार जो स्वचालित रूप से जब कतार पर नए तत्वों को जोड़ने का प्रयास कतार के सिर से तत्वों evicts और यह भरा हुआ है। एक बेदखल कतार अधिकतम आकार के साथ कॉन्फ़िगर किया जाना चाहिए। प्रत्येक बार जब एक पूर्ण कतार में तत्व जोड़ा जाता है, तो कतार स्वचालित रूप से अपने मुख्य तत्व को हटा देती है। यह परंपरागत बाध्य कतारों से अलग है, जो पूर्ण होने पर नए तत्वों को अवरुद्ध या अस्वीकार कर देता है।

    यह कक्षा थ्रेड-सुरक्षित नहीं है, और शून्य तत्वों को स्वीकार नहीं करती है।

    उदाहरण उपयोग:

    EvictingQueue<String> queue = EvictingQueue.create(2); 
    queue.add("a"); 
    queue.add("b"); 
    queue.add("c"); 
    queue.add("d"); 
    System.out.print(queue); //outputs [c, d] 
    
    0

    पहले से दिए गए उदाहरण में से कोई भी मेरी जरूरतों को पूरी तरह से बैठक कर रहे थे, तो मैं अपने ही कतार कार्यक्षमता निम्नलिखित की अनुमति देता है कि लिखा है: यात्रा, सूचकांक का उपयोग, indexOf, lastIndexOf, पहले मिल , आखिरी, ऑफ़र, शेष क्षमता, क्षमता का विस्तार, आखिरी डेक्यू, पहले डेक्यू, एनक्यू/तत्व जोड़ें, डेक्यू/निकालें तत्व, सबक्यूयूकॉपी, सबएरेपीपी, टूएरे, स्नैपशॉट, आकार जैसी मूल बातें, हटाएं या शामिल करें।

    EjectingQueue

    EjectingIntQueue

    0

    एक बहुत ही दिलचस्प परियोजना disruptor है। इसमें एक रिंगबफर है और जिसे मैं वित्तीय अनुप्रयोगों में जानता हूं उससे उपयोग किया जाता है।भी code of ringbuffer

    संबंधित मुद्दे