2008-10-10 17 views
12

व्यक्तिगत रूप से, मुझे java.util.Iterator द्वारा प्रदान की गई कार्यक्षमता की सीमा काफी दयनीय होने के लिए मिलती है। कम से कम, मैं इस तरह के रूप तरीकों करना चाहते हैं:बेहतर संग्रह Iterator

  • झांकना() इटरेटर आगे
  • पिछले (ले जाए बिना अगले तत्व देता है) पिछले तत्व

देखते हैं हालांकि रिटर्न कई अन्य संभावनाएं जैसे कि पहले() और अंतिम()।

क्या किसी को पता है कि ऐसा कोई तृतीय पक्ष इटेटरेटर मौजूद है या नहीं? इसे शायद java.util.Iterator के सजावटी के रूप में कार्यान्वित करने की आवश्यकता होगी ताकि यह मौजूदा जावा संग्रहों के साथ काम कर सके। आदर्श रूप में, यह "जेनेरिक जागरूक" होना चाहिए।

अग्रिम धन्यवाद, डॉन

उत्तर

8
+1

धन्यवाद, लेकिन अपाचे कॉमन्स संग्रह AFAIK * अभी भी * –

+0

जेनरेट नहीं किया गया है, ये दोनों लिंक अब मृत हैं – Quince

+0

लिंक को ठीक किया गया है, धन्यवाद। अपाचे अब जेनेरिक-जागरूक है, और Google संग्रह अमरूद के हिस्से के रूप में उपलब्ध हैं। – ykaganovich

9

तुम सिर्फ एक java.util.ListIterator का उपयोग करके आसानी previous() मिल सकती है। उस बिंदु पर

पीक आसानी से एक

public <T> T peek(ListIterator<T> iter) throws NoSuchElementException { 
    T obj = iter.next(); 
    iter.previous(); 
    return obj; 
} 

कर दुर्भाग्य से यह बाद से प्रत्येक संग्रह वर्ग के लिए अपने स्वयं iterators को लागू करता है एक उपयोगिता विधि के रूप में यह करने के लिए आसान हो जाएगा द्वारा कार्यान्वित किया जाता। MyListIterator जैसे कुछ इंटरफेस पर प्रत्येक संग्रह पर एक चोटी विधि प्राप्त करने के लिए एक रैपर करने के लिए काफी काम होगा।

8

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

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

0

मैंने कभी ऐसी समस्या में भाग नहीं लिया है जहां मुझे एक चोटी की आवश्यकता है(); इटरेटर ने मेरे लिए ठीक काम किया है। मैं उत्सुक हूं कि आप इसका उपयोग कैसे कर रहे हैं कि आपको लगता है कि आपको इस अतिरिक्त कार्यक्षमता की आवश्यकता है।

+0

मुझे लगता है कि सबसे आम मामला किसी प्रकार का प्रेषण है। आप यह देखने के लिए पहले तत्व को पढ़ना चाहते हैं कि इसे किसने संभालना चाहिए और प्रेषण करना चाहिए - अगर रिसीवर को पूरे अनुक्रम की आवश्यकता होती है तो उसे पास करना अच्छा होता है और हटाए गए ऑब्जेक्ट को भी पास नहीं करना पड़ता है। –

+0

मैं इसे देख सकता हूं। इसमें सिर्फ उस चीज की गंध है जो आगंतुक या कुछ जैसे किसी अन्य तरीके से कहीं अधिक आसान हो सकती है। –

3

एक बात मैं देखेंगे clojure

http://clojure.org/sequences

आधार वर्ग जावा में हैं और पूर्ण स्रोत उपलब्ध है के कार्यान्वयन में Seq कार्यान्वयन है। सीएक्स जावा इटरेटर्स पर सजावटी हैं (जावा इटरेटर इंटरफेस लेते हैं और कार्यान्वित करते हैं) - लेकिन वे अपना स्वयं का इंटरफ़ेस भी प्रदान करते हैं जो आप चाहते हैं कि अधिक से अधिक हो सकता है - या कम से कम एक प्रारंभिक बिंदु।

0

ऐसा लगता है कि आप एक ढेर का उपयोग कर से बेहतर हो सकता है।

4

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

यदि आप previous विधि चाहते हैं, तो सुझाए गए अनुसार ListIterator<> का उपयोग करें, जो तब सूचियों के रूप में व्यवहार करने वाले कंटेनर तक सीमित है।

+0

फ़ाइल तर्क वास्तव में विश्वास नहीं कर रहा है, फ़ाइल में कर्सर को आगे बढ़ाने के बिना हमें वर्तमान चरित्र (या जिसे हम पढ़ रहे हैं) प्राप्त नहीं कर पाएंगे। हालांकि, मैं मानता हूं कि 'पिछली' सुविधा प्रत्येक पुनरावर्तक (विशेष रूप से "जेनरेटर" इटरेटर द्वारा प्रदान नहीं की जा सकती है, जो प्रत्येक चरण में एक नया मान उत्पन्न करती है)। –

+0

@Luc: ऐसा इसलिए है क्योंकि आप फ़ाइलों को यादृच्छिक पहुंच के रूप में देखते हैं। और वे वास्तव में होना जरूरी नहीं है। यदि आप चाहें, तो नेटवर्क सॉकेट जैसे स्ट्रीम पर विचार करें। आप जो पढ़ते हैं उसे पढ़ते हैं, और यदि आप आगे पढ़ना चाहते हैं, तो आपको एक संपूर्ण कैशिंग तंत्र की आवश्यकता है। तो यदि आप चाहते हैं कि आपके इटरेटर को सभी परिस्थितियों में इस्तेमाल किया जाए, तो * वास्तव में * इंटरफ़ेस जावा प्रदान कर रहा है। इसके बाद, आप एडाप्टर, या अधिक विशिष्ट इटरेटर्स का उपयोग कर सकते हैं। यह रहता है कि इंटरफ़ेस जावा प्रदान जेनेरिक इटरेटर के लिए सबसे समझदार है। – PierreBdR

+0

यह यादृच्छिक पहुंच का मामला नहीं है: यहां तक ​​कि केवल अग्रेषित स्ट्रीम पर, मैं एक कारण देखने में असफल रहा हूं कि जिस मूल्य को अभी पढ़ा गया है और अगले को पढ़ना एक ही ऑपरेशन के रूप में माना जाना चाहिए। लेकिन मुझे लगता है कि यह बल्कि व्यक्तिपरक है, और हमें असहमत होने के लिए सहमत होना होगा :)। हालांकि, मैं यह जोड़ना चाहता हूं कि मुझे एक इंटरफ़ेस पर 'निकालने' विधि के लिए थोड़ा अजीब लगता है जिसे बहुत सामान्य माना जाता है, जब निकालना एक ऐसा ऑपरेशन है जो केवल अस्थिर वस्तुओं के सीमित सेट पर संभव है । –

1

जैसा कि ykaganovich ने सुझाव दिया था, आप google-collections सामानों को देखना चाहेंगे। peeking जैसे कुछ चीजों के लिए निश्चित रूप से कुछ समर्थन है। साथ ही, जैसा कि कुछ अन्य ने उल्लेख किया है, इन सभी चीजों को सभी संग्रहों के लिए कार्यान्वित करना संभावित या प्रदर्शन दृष्टिकोण से खतरनाक हो सकता है।

0

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

इटरेटर्स को उन चीज़ों पर काम करने के लिए डिज़ाइन किया गया है जो भौतिक रूप से पीछे नहीं जा सकते हैं, जिससे peek() और पिछले() दोनों असंभव हो जाते हैं।

1
public class Iterazor<T> { 
    private Iterator<T> it; 
    public T top; 
    public Iterazor(Collection<T> co) { 
    this.it = co.iterator(); 
    top = it.hasNext()? it.next(): null; 
    } 
    public void advance() { 
    top = it.hasNext()? it.next(): null; 
    } 
} 

// usage 

for(Iterazor<MyObject> iz = new Iterazor<MyObject>(MyCollection); 
    iz.top!=null; iz.advance()) 
    iz.top.doStuff(); 
} 
1

मैंने देखा कि कोई Google संग्रह से जुड़ा हुआ है, लेकिन किसी ने भी उल्लेख नहीं किया है कि जिस विधि को आप ढूंढ रहे हैं उसे Iterators.peekingIterator() कहा जाता है।

फिर भी, यदि आप केवल सूचीकरणकर्ता का उपयोग कर सकते हैं तो यह सबसे अच्छा होगा।

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