2009-06-26 25 views
17

मैं जावा मानक संग्रह पुस्तकालय में एपीआई असंगतता को समझने की कोशिश कर रहा हूं।जावा सूची इंटरफ़ेस getLast() का समर्थन क्यों नहीं करता है?

अंतिम आइटम प्राप्त करने के लिए सूची में या सार सूची में कोई विधि नहीं है, हालांकि कोई आकार के साथ अनुकरण कर सकता है और इंडेक्स() प्राप्त कर सकता है।

हालांकि, लिंक्डलिस्ट उस फ़ंक्शन का समर्थन करता है।

कोई विचार क्यों तय किया गया कि इंटरफ़ेस में इस विधि का समर्थन न करें?

+0

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

उत्तर

19

java.util.List इंटरफ़ेस getLast() का समर्थन नहीं करता है क्योंकि डिजाइनर 'न्यूनतम इंटरफ़ेस' के लिए गए थे। परिभाषित तरीकों की न्यूनतम संख्या के साथ यह समझने और सीखने में तेज़ी से दोनों आसान बनाता है।

यह 'मानवीय इंटरफ़ेस' (जैसे Ruby array class में उपयोग किया जाता है) के विपरीत है जो सामान्य संचालन करने के तरीकों को प्रदान करने का प्रयास करता है (उदा। getLast())। चूंकि ऐसे कई उपयोग हैं जो इस तरह की मौलिक अवधारणा को एक सूची के रूप में रखा जा सकता है जिससे बहुत अधिक इंटरफेस हो जाते हैं।

अधिक जानकारी के लिए मार्टिन फाउलर के Minimal Interface और Humane Interface विवरण देखें।

क्यों LinkedList getLast() का समर्थन करता है आदि, जावाडोक उद्धृत करने के लिए के रूप में:

... LinkedList वर्ग समान रूप से, मिल को हटाने और शुरुआत और सूची के अंत में एक तत्व डालने के लिए नामित किया गया तरीकों प्रदान करता है ।ये ऑपरेशन लिंक किए गए सूचियों को स्टैक, कतार, या डबल-एंडेड कतार (डेक) के रूप में उपयोग करने की अनुमति देते हैं।

संभवतः यह महसूस किया गया था कि इन विशिष्ट उपयोग मामलों के लिए एक सामान्य सूची पर्याप्त नहीं होगी।

जावा कलेक्शन एपीआई (जोशुआ ब्लोच) के मुख्य डिजाइनर के दिमाग में अंतर्दृष्टि के रूप में वह this list of API design maxims प्रदान करता है जिसके द्वारा वह काम करता है। इनमें से सबसे अधिक प्रासंगिक हैं:

एपीआई के प्रारंभिक ड्राफ्ट कम होना चाहिए, आमतौर पर कक्षा और विधि हस्ताक्षर और एक-पंक्ति विवरण वाले एक पृष्ठ होना चाहिए। यह एपीआई को पुन: स्थापित करना आसान बनाता है जब आपको पहली बार सही नहीं लगता है।

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

एपीआई को कार्यान्वयन विवरण से मुक्त रखें। वे उपयोगकर्ताओं को भ्रमित करते हैं और विकसित करने के लिए लचीलापन को रोकते हैं। यह हमेशा स्पष्ट नहीं होता है कि कार्यान्वयन विवरण क्या है: ओवरस्पेसिफिकेशन से सावधान रहें।

पहुंच को कम करें; जब संदेह में, इसे निजी बनाओ। यह एपीआई को सरल बनाता है और युग्मन को कम करता है।

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

लेकिन उन्होंने यह भी कहा गया:

ग्राहक कुछ भी कर सकता है पुस्तकालय करना मत करना। इस नियम का उल्लंघन करने से क्लाइंट में बॉयलरप्लेट कोड होता है, जो परेशान और त्रुटि-प्रवण है।

जो दिखाता है कि डिज़ाइन दिशानिर्देश अक्सर संघर्ष करते हैं और एपीआई डिज़ाइनर नौकरी का सबसे कठिन हिस्सा इन संघर्षों को संतुलित करना है।

+8

अच्छी व्याख्या। मुझे आश्चर्य है कि यद्यपि वहाँ एक विधि विधि क्यों है। – peskal

+0

@peskal जावा 8 के साथ हम isEmpty को एक विधि संदर्भ के रूप में उपयोग कर सकते हैं जो अच्छा है। –

+0

@ ThorbjørnRavnAndersen लेकिन यह जावा 8 से बहुत पहले अस्तित्व में था;) – Joffrey

2

एक इंटरफेस का लक्ष्य सबसे कम संभव सार्वजनिक तरीकों के साथ अधिकतम उपयोगिता प्रदान करना है। बेहतर तरीके से समर्थन करने के लिए कम तरीके हैं। कोई getLast() विधि नहीं है क्योंकि यह कहा जा सकता है, जैसा कि आपने कहा था।

दूसरी ओर लिंक्डलिस्ट एक ठोस कार्यान्वयन है, और इसलिए इन मुद्दों में कोई समस्या नहीं है।

संपादित करें: जैसा कि स्काफमैन ने इंगित किया है, यह मुख्य इंटरफ़ेस का लक्ष्य नहीं है। यह एक माध्यमिक लक्ष्य है जो इस इंटरफ़ेस के कार्यान्वयन को बनाए रखने में आसान बनाता है। एक इंटरफेस का मुख्य उद्देश्य उन वस्तुओं से कंक्रीट कार्यान्वयन को कम करना है जो इसका उपयोग करते हैं।

+8

नहीं , इंटरफ़ेस का लक्ष्य इंटरफ़ेस से कार्यान्वयन को अलग करना है। संचालन के प्रकार के साथ इसका कोई लेना-देना नहीं है। – skaffman

+0

मुझे यकीन नहीं है कि मैं सहमत हूं, लेकिन मुझे लगता है कि यह इस बात पर निर्भर करता है कि किसी व्यक्ति को सूची से आखिरी वस्तु क्या चाहिए। – Uri

+1

मुझे आश्चर्य है कि लिंक्ड लिस्ट/ऐरेलिस्ट में निर्मित एक अन्य getFirst() getLast() इंटरफ़ेस विधि ओ (1) नहीं होती है, इसके अलावा अन्य सूची कार्यान्वयन संभव है? – akarnokd

5

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

या यह सिर्फ एक निरीक्षण हो सकता है, या उन्हें लगा कि यह काफी आम नहीं था और यदि आपको इसकी आवश्यकता है तो आप इसे आकार/प्राप्त इंडेक्स के साथ प्राप्त कर सकते हैं।

+3

मुझे कभी-कभी इच्छा है कि उन्होंने इसे कम से कम ArrayList में भी जोड़ा होगा। Arraylist.get लिखना (arraylist.size() - 1) बार-बार एक बॉयलरप्लेट की तरह है। – akarnokd

+1

सार्वजनिक वर्ग MyArrayList ArrayList {सार्वजनिक ई getLast() {वापसी प्राप्त करें (आकार() - 1);}} – Charlie

+2

@ चार्ली: जब तक आप एक सूची इंटरफ़ेस के साथ काम नहीं करते हैं और कभी भी यह नहीं जानना चाहते कि आपका अंतर्निहित क्या है कार्यान्वयन। – Uri

1

जैसा कि आपने कहा था, सूची के साथ आप getIndex() के साथ अंतिम व्यक्ति प्राप्त कर सकते हैं, क्योंकि यह सूचकांक आधारित है। तो व्यक्तिगत रूप से मुझे इसे रखने का कोई अच्छा कारण नहीं दिखता है (क्योंकि आप इसे स्वयं लिख सकते हैं)।

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

0

getLast() को एक तरफा लिंक सूची में लागू नहीं किया जा सका। getIndex() एक तरफा लिंक्ड सूची पर शायद पूरी सूची को शुरुआत से स्कैन करेगा, इसलिए इसमें दक्षता निहितार्थ है।

+1

जब तक कि यह सिर्फ एक फ़ील्ड में अंतिम तत्व संग्रहीत नहीं करता है। आपको लगता है कि getSize() लागू किया गया है? –

+0

यही कारण है कि जावा की लिंक्डलिस्ट डबल लिंक्ड है या एकल लिंक किए गए मामले में सूची सूची के अंत में ओ (1) अतिरिक्त को अनुमति देने के लिए अपने अंतिम तत्व का संदर्भ रखती है। – akarnokd

1

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

+0

डेक इंटरफ़ेस केवल जावा 6 में पेश किया गया था। लिंक्डलिस्ट क्लास (इसकी getLast() विधि के साथ) कई संस्करणों (1.2 में पेश) से इसकी भविष्यवाणी करता है। –

0

सूची इंटरफ़ेस में उस प्रकार की कोई सुविधा विधियां नहीं हैं। कोई नहीं मिलता सबसे पहले() या getLast()। यह कड़ाई से सूचकांक आधारित है। लिंक किए गए सूची को प्रदर्शन कारणों से संभव होने पर इंडेक्स आधारित लुकअप से बचने का एक तरीका चाहिए, इसलिए GetLast वास्तव में एक अनुकूलन है, सुविधा सुविधा नहीं।

मुझे यकीन है कि डिजाइनर विधियों की मात्रा को नीचे रखना चाहते थे, इसलिए उन्होंने बहुत से संभावित तरीकों को नहीं जोड़ा।

+1

यदि आप लिंक्डलिस्ट कार्यान्वयन को देखते हैं तो इसमें इंडेक्स आधारित लॉकअप के लिए एक अनुकूलन शामिल है: यदि सूचकांक सूची के आधे आकार के बाद होता है तो ट्रैवर्सल अंत में शुरू होता है और पीछे की तरफ जाता है। इस तरह एक प्राप्त (आकार -1) व्यावहारिक रूप से getLast() के रूप में एक ही समय लागत है। – akarnokd

+0

@ kd304, यह एक कार्यान्वयन विवरण है जो इंडेक्स आधारित लुकअप के सामान्य मामले को संबोधित नहीं करता है जो लिंक्डलिस्ट के लिए इष्टतम नहीं है। लिंक्डलिस्ट पर कोई अनुबंध नहीं है जो बताता है कि कुछ इंडेक्स आधारित लुकअप तेजी से होंगे। – Yishai

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