2009-07-21 30 views
58

जावा में Iterable<T> बनाम Collection<T> का उपयोग करने के विचार क्या हैं?मुझे जावा में Iterable <T> बनाम संग्रह <T> के पैरामीटर को कब स्वीकार करना चाहिए?

उदाहरण के लिए, एक प्रकार को लागू करने पर विचार करें जो मुख्य रूप से Foo एस, और कुछ संबंधित मेटाडेटा के संग्रह से संबंधित है। इस प्रकार के निर्माता ऑब्जेक्ट सूची के एक बार प्रारंभिकरण की अनुमति देता है। (मेटाडाटा बाद में सेट किया जा सकता है।) इस कन्स्ट्रक्टर को किस प्रकार का स्वीकार करना चाहिए? Iterable<Foo>, या Collection<Foo>?

इस निर्णय के लिए क्या विचार हैं?

पैटर्न ऐसे ArrayList के रूप में पुस्तकालय प्रकार द्वारा निर्धारित (जो किसी भी Collection से initialised किया जा सकता है, लेकिन एक Iterable नहीं) मेरे नेतृत्व Collection<Foo> उपयोग करने के लिए होता है के बाद।

लेकिन क्यों Iterable<Foo> स्वीकार नहीं करते हैं, यह देखते हुए कि प्रारंभिकरण आवश्यकताओं के लिए यह पर्याप्त है? सख्ती से आवश्यक (Iterable) की तुलना में, उपभोक्ता से उच्च स्तर की कार्यक्षमता (Collection) क्यों मांगें?

+2

इस बारे में एक महान लेख [यहां] [1] है। [1]: http://www.artima.com/weblogs/viewpost.jsp?thread=119193 – amischiefr

उत्तर

53

कई Iterable<T> से पहले से ही अस्तित्व में (जो केवल 1.5 में पेश किया गया था) - एक निर्माता Iterable<T>के साथ-साथCollection<T> स्वीकार करने के लिए, लेकिन मौजूदा निर्माता बदलते एक तोड़ने परिवर्तन हो गया होता जोड़ने के लिए कोई कारण नहीं था।

व्यक्तिगत रूप से मैं Iterable<T> का उपयोग करूंगा यदि यह आपको वह सब कुछ करने की अनुमति देता है जो आप चाहते हैं। यह कॉलर्स के लिए अधिक लचीला है, और विशेष रूप से यह आपको Google जावा संग्रह (और इसमें कोई संदेह नहीं है) के उपयोग से अपेक्षाकृत आसान फ़िल्टरिंग/प्रक्षेपण/आदि करने देता है।

+0

आप कहते हैं कि यह "ब्रेकिंग चेंज" होगा। क्या होगा (कहें) ArrayList कलेक्टर पैरामीटर संग्रह से Iterable में बदल दिया गया था? – finnw

+16

@finnw: यह स्रोत-संगत होगा, लेकिन बाइनरी-संगत नहीं होगा: मौजूदा कन्स्ट्रक्टर का उपयोग कर मौजूदा (संकलित) कक्षाएं तोड़ेंगी (क्योंकि वे संग्रह-पैरामीटर-कन्स्ट्रक्टर को स्पष्ट रूप से कॉल करते हैं) और फिर से संकलित करने की आवश्यकता है। –

1

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

+7

मैं असहमत हूं - Iterable अभी भी संग्रह को तर्क के रूप में लेने देता है, लेकिन जैसा कि जॉन कहता है कि आप अन्य कक्षाओं में प्रवेश करने की अनुमति देते हैं जो आपको अपने तत्वों पर कदम उठाने देता है। यदि यह आपकी आवश्यक कार्यक्षमता है, तो यह एक बेहतर विकल्प है। आपके जावाडॉक्स को वैसे भी तर्क दस्तावेज करना चाहिए, और यदि आपके बाद आने वाले लोग कोर जावा कक्षाओं से परेशान हैं तो शायद गहरे मुद्दे हैं। ;-) –

+3

मैं पॉल के साथ हूं। मैं शायद ही कभी अपने वर्गों या पुस्तकालयों में, इटरटेबल देखता हूं। मैं संग्रह को और अधिक देखता हूं, और सबसे अधिक बार सूचीबद्ध करता हूं। मुझे लगता है कि Iterable की पसंद के पीछे तर्क है, लेकिन मुझे लगता है कि मौजूदा मुहावरे संग्रह है। शायद यह Iterables होना चाहिए, और शायद यह होगा, किसी दिन, लेकिन अभी के लिए, मैं एक संग्रह से कम आश्चर्यचकित होगा। –

+1

** बीओओ !! ** –

-1

आप सही हैं, क्योंकि आपको जो चाहिए वह सबसे सामान्य रूप से पूछने के लिए अच्छा अभ्यास माना जाता है।

8

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

2

यदि आप संग्रह के लिए जाते हैं, तो आपकी कक्षा केवल संग्रह से शुरू की जा सकती है, अगर आप इटरटेबल के लिए जाते हैं, तो आप या तो संग्रह या पुनरावर्तक से प्रारंभ कर सकते हैं।

दोनों के लिए प्रयास और प्रदर्शन समान होने वाला है, यह कन्स्ट्रक्टर में इटेबल को स्वीकार करने की पूरी समझ बनाता है।

14

एक IterableIterator ऑब्जेक्ट्स का उत्पादन करता है। परिभाषा के अनुसार ऑब्जेक्ट, पुनरावृत्त करता है। ध्यान दें, Iterator इंटरफ़ेस को hasNext()false से पहले कितनी बार कॉल किया जा सकता है, इस बारे में कोई वादा नहीं करता है। एक Iterator विधि false से पहले Integer.MAX_VALUE + 1 मानों से अधिक संभवतः फिर से चला सकता है।

हालांकि, CollectionIterable का एक विशेष रूप है। क्योंकि Collection में Integer.MAX_VALUE तत्व नहीं हैं (size() विधि के आधार पर), यह स्वाभाविक रूप से माना जाता है कि इसकी Iterator ऑब्जेक्ट्स इस कई तत्वों पर पुन: सक्रिय नहीं होंगे।

इसलिए, एक Iterable की तुलना में एक Collection को स्वीकार करने के बजाय द्वारा, अपने वर्ग कितने तत्वों में पारित किया जा रहा है पर कुछ गारंटी हो सकता है। यह विशेष रूप से वांछनीय है अगर अपनी कक्षा में ही एक Collection है।

बस मेरे दो सेंट ...

+4

जो गैर-संग्रह, पूरी तरह से उचित पुनरावृत्तियों को अस्वीकार करने के खर्च पर काफी * अनुचित * पुनरावृत्तियों को अस्वीकार करता है। –

+11

और, वास्तव में, 'संग्रह' Interger.MAX_VALUE से भी बड़ा हो सकता है, फिर आकार विधि केवल Integer.MAX_VALUE लौटाती है। 'कलेक्शन' का लाभ ज्यादातर 'आकार()' विधि है (सबकुछ इटरेटर और आकार के शीर्ष पर लागू किया जा सकता है, जैसा कि सारकोलेक्शन शो), इसलिए संग्रह ** का उपयोग करें जब आपको इसे पुन: प्रारंभ करने से पहले आकार की आवश्यकता हो, जब आप केवल पुनरावृत्ति करना नहीं चाहते हैं। –

+1

@ Paŭlo: वाह, मुझे नहीं पता था कि 'Collection.size() 'रिटर्न' Integer.MAX_VALUE' अगर इसमें कई तत्वों से अधिक है! –

4

कुछ रचनाकार, उदा। ArrayList (संग्रह सी), दक्षता के लिए संग्रह की toArray() विधि का उपयोग करें।

3

देखें "Iterators और Iterables पर इतना जोर क्यों?" Google Collection FAQ पर Iterators पसंद करने के लिए एक सभ्य तर्क के लिए, खासकर जब बहुत सारे डेटा से निपटने के लिए। एक समानता जो मदद कर सकती है वह केवल पढ़ने के लिए केवल कर्सर और स्क्रोल करने योग्य कर्सर के बीच अंतर को सोचना है।

7

Spring Data JPA के उपयोगकर्ता प्रकार के Repositories वापसी संग्रह Iterable<T>.

परियोजनाओं मैं पिछले कि Spring प्रयोग पर काम किया है, मैं पाया है कि पुनः प्राप्ति है के बाद एक संग्रह पर काम करने की जरूरत मिलेगा संग्रह से ऑब्जेक्ट T का चयन करने के लिए अक्सर Collection<T> की बजाय व्यापार परत में Iterable<T> का उपयोग किया जाता है।

सभी संग्रह कर रहे हैं Iterable (कि इंटरफेस जो Collection इंटरफ़ेस का विस्तार है, इसलिए नहीं Map है!), तो व्यापार परत में Iterable का उपयोग कर केवल अपने सुपर प्रकार से एक संग्रह की चर्चा करते हुए का एक मामला है और अभी भी उपयोग की अनुमति देता for-each पुनरावृत्त करने के लिए।

आप एक संग्रह की सामग्री में हेरफेर करने की जरूरत है, एक सुविधा की विधि आप एक नया Collection पॉप्युलेट करने की अनुमति होगी, तो आप मूल संग्रह डेटा के साथ , remove(), आदि का उपयोग कर सकते हैं।

वैकल्पिक रूप से, इस उद्देश्य के लिए Google Guava और Apache Commons जैसे लोकप्रिय तृतीय पक्ष API द्वारा सुविधा विधियां प्रदान की जाती हैं।

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