2012-07-02 39 views
35

स्केल में Iterator और Iterable के बीच क्या अंतर है?Iterable और Iterator के बीच संबंध क्या है?

मैंने सोचा कि Iterable एक सेट का प्रतिनिधित्व करता है जिसे मैं पुन: सक्रिय कर सकता हूं, और Iterator पुनरावर्तक सेट में से किसी एक आइटम के लिए "पॉइंटर" है।

हालांकि, Iterator में forEach, map, foldLeft जैसे कार्य हैं। इसे के माध्यम से Iterable में परिवर्तित किया जा सकता है। और, उदाहरण के लिए, scala.io.Source.getLinesIterator लौटाता है, Iterable नहीं।

लेकिन मैं groupByIterator पर नहीं कर सकता और मैं इसे Iterable पर कर सकता हूं।

तो, उन दो, Iterator और Iterable के बीच संबंध क्या है?

उत्तर

50

संक्षेप में: Iterator में राज्य है, जबकि Iterable नहीं है।

दोनों के लिए एपीआई दस्तावेज़ देखें।

Iterable:

iterable संग्रह के लिए एक आधार विशेषता।

यह सभी स्कैला संग्रहों के लिए एक मूल विशेषता है जो एक पुनरावर्तक विधि को संग्रहित तत्वों के एक-एक करके चरणबद्ध करने के लिए परिभाषित करता है। [...] यह विशेषता इटरेटर का उपयोग करके सभी तत्वों के माध्यम से को चरणबद्ध करके Iterable की foreach विधि लागू करता है।

Iterator:

Iterators डाटा संरचनाओं कि तत्वों के एक दृश्य से अधिक पुनरावृति करने की अनुमति है। उनके पास अगला तत्व उपलब्ध है या नहीं, और अगली विधि लौटाती है और इसे पुनरावर्तक से हटा देती है, यह जांचने के लिए उनके पास अगला है।

एक पुनरावर्तक उत्परिवर्तनीय है: इसके अधिकांश संचालन इसके राज्य को बदलते हैं। जबकि इसे अक्सर संग्रह के तत्वों के माध्यम से पुन: उपयोग करने के लिए उपयोग किया जाता है, यह का उपयोग किसी संग्रह द्वारा समर्थित किए बिना भी किया जा सकता है (साथी ऑब्जेक्ट पर कन्स्ट्रक्टर देखें)।

Iterator के साथ आप एक पुनरावृत्ति रोक सकते हैं और यदि आप चाहें तो इसे जारी रख सकते हैं। आप एक Iterable के साथ ऐसा करने की कोशिश अगर यह फिर से सिर से शुरू हो जाएगा:

scala> val iterable: Iterable[Int] = 1 to 4 
iterable: Iterable[Int] = Range(1, 2, 3, 4) 

scala> iterable.take(2) 
res8: Iterable[Int] = Range(1, 2) 

scala> iterable.take(2) 
res9: Iterable[Int] = Range(1, 2) 

scala> val iterator = iterable.iterator 
iterator: Iterator[Int] = non-empty iterator 

scala> if (iterator.hasNext) iterator.next 
res23: AnyVal = 1 

scala> if (iterator.hasNext) iterator.next 
res24: AnyVal = 2 

scala> if (iterator.hasNext) iterator.next 
res25: AnyVal = 3 

scala> if (iterator.hasNext) iterator.next 
res26: AnyVal = 4 

scala> if (iterator.hasNext) iterator.next 
res27: AnyVal =() 

ध्यान दें, कि मैं Iterator पर take उपयोग नहीं किया। इसका कारण यह है कि इसका उपयोग करना मुश्किल है। hasNext और next केवल दो विधियां हैं जिन्हें Iterator पर अपेक्षित काम करने की गारंटी है।Scaladoc फिर देखें:

यह ध्यान रखें कि, जब तक अन्यथा न कहा गया विशेष महत्व का है, भी उस पर एक विधि बुला के बाद पुनरावर्तक का उपयोग कभी नहीं करना चाहिए। दो सबसे महत्वपूर्ण अपवाद भी एकमात्र अमूर्त विधियां हैं: अगला और है अगला।

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

सुरक्षित और असुरक्षित उपयोग के लिए इस उदाहरण पर विचार:

def f[A](it: Iterator[A]) = { 
    if (it.hasNext) {   // Safe to reuse "it" after "hasNext" 
    it.next     // Safe to reuse "it" after "next" 
    val remainder = it.drop(2) // it is *not* safe to use "it" again after this line! 
    remainder.take(2)   // it is *not* safe to use "remainder" after this line! 
    } else it 
} 
+1

धन्यवाद, उदाहरण के साथ, यह सही समझ में आता है। –

+0

ओडर्स्की और चम्मच ने स्कैला संग्रह कक्षाओं पर एक अच्छा प्राइमर लिखा: देखें http://www.scala-lang.org/docu/files/collections-api/collections.html –

+0

मैंने इसका परीक्षण स्कैला 2.11.7 में किया है, इटेटरेटर समान रूप से व्यवहार करता है, अर्थात्, जब आप दूसरी बार 'ले लें (2)' का आह्वान करते हैं, तो आपको अभी भी 'सूची (1, 2) 'मिलती है। – qed

5

मार्टिन ओडर्स्की और लेक्स चम्मच से एक अन्य स्पष्टीकरण:

वहाँ iterators और पर foreach विधि के बीच एक महत्वपूर्ण अंतर है ट्रैवर्सबल संग्रहों पर एक ही विधि: जब को एक इटरेटर पर बुलाया जाता है, तो होने पर foreach iterator को इसके अंत में छोड़ देगा। तो एक ही पुनरावर्तक पर अगली बार कॉलिंग NoSuchElementException के साथ विफल हो जाएगी। इसके विपरीत, जब संग्रह पर बुलाया जाता है, फ़ोरैच संग्रह में तत्वों की संख्या को अपरिवर्तित (जब तक पारित कार्य तत्वों को हटाने के लिए जोड़ता है, तब तक छोड़ देता है, लेकिन यह निराश होता है, क्योंकि इससे आश्चर्यजनक परिणाम हो सकते हैं)।

स्रोत: http://www.scala-lang.org/docu/files/collections-api/collections_43.html

यह भी ध्यान रखें (इस टिप के लिए वी-चिंग लिन के लिए धन्यवाद) Iterator जबकि Iterable नहीं है TraversableOnce विशेषता फैली हुई है।

0

यह भी ध्यान रखें (धन्यवाद इस टिप के लिए वी-चिंग लिन के लिए) इटरेटर TraversableOnce विशेषता जबकि Iterable नहीं फैली हुई है।

स्कैला 2.11 में इटरेटर और इटारेबल दोनों ट्रैवर्सएबल एक बार विशेषता को बढ़ाता है।

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