2015-09-02 11 views
74

क्या कोई अच्छा कारण है कि java.utils पैकेज में विधि List<T> के बजाय ArrayList<T> देता है?गणना को ArrayList में क्यों परिवर्तित किया जाता है और java.utils में सूचीबद्ध नहीं होता है?

स्पष्ट रूप से ArrayListList है, लेकिन मुझे लगता है कि कार्यान्वयन प्रकार के बजाय इंटरफ़ेस प्रकार को वापस करने के लिए आम तौर पर अच्छा अभ्यास है।

+0

जावाडोक से: "_ एक सरणी सूची पुन: प्रस्तुत करता है [...] _"। उन्होंने 'एरेलेलिस्ट' वापस करने के लिए एपीआई को लॉक करने का फैसला क्यों किया, और हम 'कलेक्शन' के स्रोत कोड को देखते समय भी संभवतः इस प्रश्न का उत्तर नहीं दे सकते। – Laf

+0

हो सकता है क्योंकि enums के क्रम को बनाए रखा जाना चाहिए? आपके प्रश्न में दिए गए लिंक में इसका उल्लेख किया गया है, _ निर्दिष्ट गणना द्वारा लौटाए गए तत्वों को समेकित करता है जिसमें वे enumeration_ –

+5

@ Amit.rk3 द्वारा वापस लौटाए गए क्रम में एक सूची [http://docs.oracle.com) /javase/7/docs/api/java/util/List.html) आपके द्वारा चुने गए कार्यान्वयन को हमेशा आदेश देता है। –

उत्तर

54

अस्वीकरण: मैं एक JDK लेखक नहीं हूँ।

मैं मानता हूँ कि यह इंटरफेस करने के लिए अपने खुद कोड लिखने के लिए सही है, लेकिन यदि आप एक तीसरी पार्टी के लिए एक परिवर्तनशील संग्रह लौट जा रहे हैं, यह तीसरे पक्ष बताने के लिए महत्वपूर्ण है List किस तरह वे वापस आ रहे हैं।

LinkedList और ArrayList विभिन्न परिचालनों के लिए बहुत अलग, प्रदर्शन के अनुसार हैं। उदाहरण के लिए, ArrayList का पहला तत्व O(n) है, लेकिन LinkedList का पहला तत्व O(1) है।

पूरी तरह से वापसी प्रकार निर्दिष्ट करके, JDK लेखकों अतिरिक्त जानकारी, स्पष्ट कोड में, वस्तु किस तरह वे आपको वापस दे रहे हैं, तो आप इस विधि का ठीक से उपयोग करने के लिए अपने कोड लिख सकते हैं के बारे में संवाद स्थापित करने हैं। यदि आपको वास्तव में LinkedList की आवश्यकता है, तो आप जानते हैं कि आपको यहां एक निर्दिष्ट करना होगा।

अंत में, कार्यान्वयन पर एक इंटरफ़ेस को कोड करने का मुख्य कारण यह है कि यदि आपको लगता है कि कार्यान्वयन बदल जाएगा। जेडीके लेखकों को शायद यह पता चलता है कि वे कभी इस विधि को बदलने जा रहे हैं; यह कभी भी LinkedList या Collections.UnmodifiableList वापस नहीं जा रहा है। हालांकि, ज्यादातर मामलों में, आप शायद अभी भी करना होगा:

List<T> list = Collections.list(enumeration); 
+19

ऐसा लगता है कि यह एपीआई डिज़ाइन के लिए पोस्टेल लॉ का एक प्रकार है: अपने इनपुट के साथ सामान्य रहें, अपने आउटपुट के साथ विशिष्ट रहें। –

+2

एक दिन वे 'toLinkedList' विधि जोड़ देंगे, और फिर ArrayList संस्करण के लिए नाम 'सूची' मूर्खतापूर्ण लगेगा। – immibis

+1

मुझे लगता है कि यहां महत्वपूर्ण जानकारी गीली है, सूची उत्परिवर्तनीय है या नहीं। जैसे इंटरफ़ेस के कौन से तरीके एक असमर्थितऑपरेशन अपवाद फेंकते हैं और जो नहीं करते हैं। – keuleJ

31

List लौटने पर, आप प्रोग्राम को इंटरफ़ेस पर प्रचारित करेंगे, जो एक बहुत अच्छा अभ्यास है। हालांकि, इस दृष्टिकोण की सीमा है। उदाहरण के लिए, आप ArrayList के लिए परिभाषित कुछ विधियों का उपयोग नहीं कर सकते हैं और List इंटरफ़ेस में मौजूद नहीं हैं - विवरण के लिए this answer देखें।

मैं जावा ™ ट्यूटोरियल से API Design के हवाले कर रहा हूँ:

... यह किसी भी प्रकार लागू करता कि या संग्रह इंटरफेस की एक फैली हुई है की एक वस्तु लौटने के लिए ठीक है । यह इंटरफेस या एक विशेष उद्देश्य प्रकार में से एक हो सकता है जो इन इंटरफेस में से किसी एक को बढ़ाता या लागू करता है।

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

ArrayList अनिवार्य रूप से एक सरणी है, जब मुझे "संग्रह-सरणी" की आवश्यकता होती है तो वे मेरी पहली पसंद हैं। इसलिए यदि मैं गणना सूची में कनवर्ट करना चाहता हूं, तो मेरी पसंद एक सरणी सूची होगी।

किसी अन्य मामलों में, यह अभी भी लिखने के लिए वैध है:

List<T> list = Collections.list(e); 
+4

"सबसे सामान्य के बजाय सबसे विशिष्ट लागू संग्रह इंटरफ़ेस" के बारे में, यह समझ में आता है, लेकिन एक ArrayList एक इंटरफ़ेस नहीं है। इस मामले में, सूची सबसे विशिष्ट इंटरफ़ेस प्रतीत होती है। –

+2

'सॉर्टेड मैप' के मामले में, यह सामान्य 'मानचित्र' में कार्यक्षमता जोड़ता है, इसलिए मुझे लगता है कि इसे रिटर्न प्रकार के रूप में निर्दिष्ट करना समझ में आता है। हालांकि, 'ArrayList'' सूची 'में कुछ भी नहीं जोड़ता है, और उसे' लिंक्डलिस्ट 'के साथ बदल दिया जा सकता है और आप कुछ भी अलग नहीं देखेंगे (कार्यक्षमता-वार, प्रदर्शन-वार नहीं)। फिर भी, मुझे लगता है कि आपका संदर्भ बहुत दिलचस्प है। +1। – Laf

+1

@Laf वास्तव में 'लिंक्डलिस्ट' या 'ऐरेलिस्ट' चुनते समय कई चीजों पर विचार करना चाहिए। समय-जटिलता प्राप्त करने की तरह .. – Maroun

6

कार्य जो नव निर्मित अस्थायी वस्तुओं के "अनन्य स्वामित्व" वापस अक्सर सबसे विशिष्ट प्रकार व्यावहारिक होना चाहिए; जो अपरिवर्तनीय वस्तुओं को वापस करते हैं, खासकर यदि उन्हें साझा किया जा सकता है, तो अक्सर कम-विशिष्ट प्रकारों को वापस करना चाहिए।

भेद का कारण यह है कि पूर्व मामले में, एक वस्तु हमेशा संकेतित प्रकार की एक नई वस्तु का उत्पादन करने में सक्षम होगी, और चूंकि प्राप्तकर्ता ऑब्जेक्ट का मालिक होगा और कोई यह नहीं बताएगा कि प्राप्तकर्ता क्या काम कर सकता है निष्पादित करने के लिए, ऑब्जेक्ट को वापस लौटने वाले कोड के लिए कोई रास्ता नहीं होगा, यह जानने के लिए कि कोई वैकल्पिक इंटरफ़ेस कार्यान्वयन प्राप्तकर्ता की ज़रूरतों को पूरा कर सकता है या नहीं।

बाद के मामले में, तथ्य यह है कि ऑब्जेक्ट अपरिवर्तनीय है कि फ़ंक्शन एक वैकल्पिक प्रकार की पहचान करने में सक्षम हो सकता है जो सबकुछ कर सकता है और अधिक जटिल प्रकार अपनी सटीक सामग्री दे सकता है। उदाहरण के लिए, Immutable2dMatrix इंटरफ़ेस को ImmutableArrayBacked2dMatrix वर्ग और ImmutableDiagonal2dMatrix कक्षा द्वारा कार्यान्वित किया जा सकता है। एक स्क्वायर Immutable2dMatrix को वापस करने वाला एक फ़ंक्शन ImmutableDiagonalMatrix उदाहरण वापस करने का निर्णय ले सकता है यदि मुख्य विकर्ण से सभी तत्व शून्य हो जाते हैं, या ImmutableArrayBackedMatrix नहीं है। पूर्व प्रकार में बहुत कम भंडारण स्थान लगेगा, लेकिन प्राप्तकर्ता को उनके बीच के अंतर की परवाह नहीं करनी चाहिए।

कंक्रीट ImmutableArrayBackedMatrix के बजाय Immutable2dMatrix लौटने पर कोड को सरणी के आधार पर रिटर्न प्रकार चुनने की अनुमति मिलती है; इसका यह भी अर्थ है कि यदि कोड को सरणी वापस करने के लिए माना जाता है तो Immutable2dMatrix का उपयुक्त कार्यान्वयन हो रहा है, यह एक नया उदाहरण बनाने के बजाय इसे वापस कर सकता है। अपरिवर्तनीय वस्तुओं के साथ काम करते समय इन दोनों कारकों में प्रमुख "जीत" हो सकती है।

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

1

छोटे कॉलिंग विधियों में ओवरहेड एक ऑब्जेक्ट पर सीधे एक इंटरफेस के बजाय एक इंटरफ़ेस है।

यह ओवरहेड अक्सर 1 या 2 प्रोसेसर निर्देशों से अधिक नहीं होता है। यदि विधि जानता है कि विधि अंतिम है तो विधि को कॉल करने का ओवरहेड भी कम है।यह आपके और मेरे सही कोड के लिए मापनीय नहीं है, लेकिन java.utils में निम्न स्तर के तरीकों के लिए कुछ कोड में उपयोग किया जा सकता है जहां यह एक मुद्दा है।

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

स्पष्ट रूप से java.utils के लेखकों को यह जानने का कोई तरीका नहीं है कि संग्रह.सूची() को क्या सॉफ़्टवेयर कहते हैं और परिणामस्वरूप यह सॉफ़्टवेयर पुन: परीक्षण करने का कोई तरीका नहीं है यदि वे Collections.list() के इम्प्लांटेशन को बदलते हैं। इसलिए वे एक अलग प्रकार की सूची वापस करने के लिए Collections.list() के इम्प्लांटेशन को बदलने के लिए नहीं जा रहे हैं, भले ही टाइप सिस्टम ने इसे अनुमति दी हो!

अपने स्वयं के सॉफ़्टवेयर लिखते समय, आप (उम्मीद है) स्वचालित परीक्षण है जो आपके सभी कोड को कवर करता है और आपके कोड से संबंधित कैसे होता है, इस बारे में अच्छी समझ है कि प्रदर्शन कहां है। कॉलर्स को बदलने के बिना, किसी विधि में बदलाव करने में सक्षम होने के कारण सॉफ्टवेयर का डिज़ाइन बदल रहा है।

इसलिए व्यापार बंद के दो सेट बहुत अलग हैं।

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