कलेक्शंस। खाली नक्शा () बनाम नया हैशपॉप ()


143

ऐसी कौन सी परिस्थितियाँ हैं जहाँ मैं उपयोग कर सकता हूँ Collections.emptyMap()? प्रलेखन कहता है कि मैं इस पद्धति का उपयोग कर सकता हूं यदि मैं चाहता हूं कि मेरा संग्रह अपरिवर्तनीय हो।

मुझे एक अपरिवर्तनीय खाली संग्रह क्यों चाहिए? मुद्दा क्या है?


12
+1 के सवाल पर क्योंकि मैंने उस स्थैतिक विधि को पहले कभी नहीं देखा है
टिम बेंडर

तुम भी scala लेंस गूगल scala लेंस पर एक नज़र हो सकता है । रिक्तिका और इम्यूटेबल मैप का उपयोग वस्तुओं को बनाने के लिए किया जा सकता है, जो अपरिवर्तनीय हैं। रिक्त स्थान प्रारंभिक बिंदु है। हर बार जब कोई तत्व जोड़ा जाता है तो मानचित्र को पुराने तत्व और नए तत्वों वाले नक्शे से बदल दिया जाता है। मुद्दा यह है, कि वस्तु तक पहुँच सुरक्षित है।
michael_s

1
यह ऑब्जेक्टिव-सी की तरह है [NSArray array], यह एक ऐसी वस्तु लौटाता है जो हालांकि प्रयोग करने योग्य नहीं है लेकिन मौजूद है। तो आप इसे एक सामान्य वस्तु की तरह खेल सकते हैं और त्रुटि नहीं पा सकते।
शेन हू

जवाबों:


144

से प्रभावी जावा , मद # 43 - "Return empty arrays or collections, not null"एक खाली संग्रह लौटने को दर्शाता है और शायद यह भी इन का उपयोग दर्शाता है emptyList(), emptySet()और emptyMap()संग्रह वर्ग पर तरीकों एक खाली संग्रह भी अडिग होने का अतिरिक्त लाभ है कि प्राप्त करने के लिए। से # 15 मद "Minimize Mutability"

से संग्रह-emptySet-संग्रह-emptyList-संग्रह

इसका एक प्रकार का प्रोग्रामिंग मुहावरा। यह उन लोगों के लिए है जो अशक्त चर नहीं चाहते हैं। इसलिए सेट शुरू होने से पहले, वे खाली सेट का उपयोग कर सकते हैं।

नोट: नीचे दिया कोड केवल एक उदाहरण है (इसे अपने उपयोग मामले के अनुसार बदलें):

private Set myset = Collections.emptySet();

void initSet() {
   myset = new HashSet();
}
void deleteSet() {
   myset = Collections.emptySet();
}

ये तरीके कुछ फायदे प्रदान करते हैं:

  1. वे अधिक संक्षिप्त हैं क्योंकि आपको संग्रह के सामान्य प्रकार को स्पष्ट रूप से टाइप करने की आवश्यकता नहीं है - यह आमतौर पर विधि कॉल के संदर्भ से अनुमान लगाया गया है।

  2. वे अधिक कुशल हैं क्योंकि वे नई वस्तुओं को बनाने से परेशान नहीं होते हैं; वे सिर्फ एक मौजूदा खाली और अपरिवर्तनीय वस्तु का फिर से उपयोग करते हैं। यह प्रभाव आम तौर पर बहुत मामूली होता है, लेकिन यह कभी-कभार (अच्छी तरह से, शायद ही कभी) महत्वपूर्ण होता है।


15
प्रभावी जावा संदर्भ के लिए +1। एक नाइट: मैं विधि और दोस्तों के पूरे बिंदु के बाद से पैरामीटर Setऔर HashSetआपके उदाहरणों में सिफारिश करूंगा emptySet()(जैसा कि स्थिरांक Collections.EMPTY_SETआदि के विपरीत है ) यह है कि वे जेनरिक के साथ अच्छी तरह से खेलते हैं। इसके अलावा, एक सुविधा (कच्चे प्रकार) का उपयोग करना जो कि जावा 5 के बाद से हटा दिया गया है, एक अच्छी शिक्षण सहायता नहीं है।
डैनियल प्रीडन

4
मैं असंबद्ध रहता हूं ... निम्नलिखित कार्यों पर फेंक दिए जाने से बचने के Collectionबजाय उपयोग करने का संपूर्ण बिंदु नहीं है ? एक अपरिवर्तनीय संग्रह का उपयोग करने के परिणामस्वरूप मुझे किसी अन्य प्रकार के अपवाद की कल्पना होती है। और असाइन करना सबसे निश्चित रूप से अपरिवर्तनीय स्थिरांक प्रदान करने से कम कुशल नहीं है। nullExceptionsnull
fgysin ने मोनिका

14
@fgysin: यदि आपके पास एक एपीआई है जहां ग्राहकों से संग्रह को संशोधित करने की उम्मीद की जाती है, तो हाँ, यह एक अपरिवर्तनीय संग्रह को वापस करने के लिए समझ में नहीं आता है। लेकिन अगर आपके पास एक एपीआई है जहां आप एक संग्रह लौटाते हैं जिसे ग्राहकों को संशोधित नहीं करना चाहिए और बस उस पर पुनरावृति करना चाहिए, तो अंतर्निहित संग्रह के लिए एक दृश्य वापस करना सही अर्थ में यह सुनिश्चित करता है कि "खराब" ग्राहक गलती से संग्रह को संशोधित न करे। आप से। रिक्त के बजाय खाली संग्रह लौटाने का मतलब है कि आपके ग्राहक को संग्रह का उपयोग करने से पहले एक शून्य जांच करने की आवश्यकता नहीं है, जिससे ग्राहक कोड स्पष्ट हो जाएगा।
जीन होमिनल

4
public boolean setExists() { return !myset.equals(Collections.emptySet()); }
assylias

5
आपके उदाहरण में आप खाली सेट के लिए स्पष्ट रूप से जाँच कर रहे हैं और इसे एक प्रहरी मूल्य के रूप में उपयोग कर रहे हैं, और आपकी कक्षा में परिवर्तनशील है। आपका छोटा उदाहरण सेंटिनल्स और म्यूटेबिलिटी का उपयोग करता है, जो कि वास्तव में कलेक्शंस। हेम्पसेट () को रोकने की कोशिश कर रहा है।
मार्क O'Morain

33

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

public ResultSet executeQuery(String query, Map<String, Object> queryParameters);

यदि आपके पास कोई क्वेरी है जो किसी भी पैरामीटर को नहीं लेती है, तो निश्चित रूप से एक HashMap बनाने के लिए थोड़ा बेकार है, जिसमें एक सरणी आवंटित करना शामिल है, जब आप बस 'खाली मानचित्र' में पास कर सकते हैं जो प्रभावी रूप से एक निरंतर है, जिस तरह से इसे लागू किया जाता है। में है java.util.Collections


22

मुझे एक अपरिवर्तनीय खाली संग्रह क्यों चाहिए? मुद्दा क्या है?

यहां दो अलग-अलग अवधारणाएं हैं जो एक साथ देखे जाने पर अजीब लगती हैं। जब आप दो अवधारणाओं को अलग-अलग मानते हैं तो यह अधिक समझ में आता है।

  • सबसे पहले, आपको जहां भी संभव हो, एक परिवर्तनशील के बजाय एक अपरिवर्तनीय संग्रह का उपयोग करना पसंद करना चाहिए। Immuablity के लाभ कहीं और अच्छी तरह से प्रलेखित हैं

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

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


8

ऐसे कई मामले हैं जहां आप अपरिवर्तनीय नक्शे, सूची, सेट या अन्य प्रकार के संग्रह का उपयोग करना पसंद करेंगे।

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

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

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

मैं इसे "वैल्यू बाय पास" सम्मेलन के रूप में सोचता हूं ।

आम तौर पर - जब भी डेटा मॉड्यूल या सेवा सीमाओं को पार करता है, तो एक अपरिवर्तनीय डेटा संरचनाओं का उपयोग करने के लिए यह एक समझदार अभ्यास है। इससे (अपरिवर्तनीय) इनपुट / आउटपुट और परस्पर आंतरिक स्थिति के बीच अंतर के बारे में तर्क करना बहुत आसान हो जाता है।

इस के एक बहुत ही लाभदायक साइड इफेक्ट के रूप में आपके मॉड्यूल / सेवाओं की सुरक्षा और थ्रेड सुरक्षा में वृद्धि हुई है और यह चिंताओं को साफ करने के लिए अलग है।

Collections.empty*()तरीकों का उपयोग करने का एक और अच्छा कारण उनकी क्रियात्मकता की ध्यान देने योग्य कमी है। पूर्व-जावा 7 युग में, यदि आपके पास एक सामान्य संग्रह था, तो आपको पूरे स्थान पर सामान्य प्रकार के एनोटेशन छिड़कने होंगे।

बस इन दो घोषणाओं की तुलना करें:

Map<Foo, Comparable<? extends Bar>> fooBarMap = new HashMap<Foo, Comparable<? extends Bar>>();

बनाम:

Map<Foo, Comparable<? extends Bar>> fooBarMap = Collections.emptyMap();

उत्तरार्द्ध स्पष्ट रूप से दो महत्वपूर्ण तरीकों से पठनीयता पर जीत हासिल करता है:

  1. पहले घोषणापत्र में, एक खाली नक्शे की पूरी तात्कालिकता को सामान्य प्रकार की घोषणाओं के शोर में दफन किया जाता है, जो अनिवार्य रूप से तुच्छ घोषणा को बहुत अधिक गूढ़ बनाता है।
  2. दाईं ओर जेनेरिक प्रकार के एनोटेशन की उल्लेखनीय कमी के अलावा, दूसरा संस्करण स्पष्ट रूप से बताता है कि नक्शे को एक खाली नक्शे के लिए आरंभीकृत किया गया है। इसके अलावा - यह जानते हुए कि यह विधि एक अपरिवर्तनीय मानचित्र लौटाती है, अब मेरे लिए यह खोजना आसान है कि कहां fooBarMapपर एक और गैर-रिक्त मान असाइन किया जा रहा है /fooBarMap =/

5

एक के लिए, आप संदर्भ साझा करने से दूर हो सकते हैं। एक new HashMap()आदि को एक आवंटित वस्तु की आवश्यकता होगी, और संभवतः डेटा को रखने के लिए कुछ अतिरिक्त तत्वों की आवश्यकता होगी, लेकिन आपको केवल एक अपरिवर्तनीय खाली संग्रह (सूची, सेट, मानचित्र, या किसी अन्य) की एक प्रति चाहिए। यह एक स्पष्ट विकल्प है जब एक विधि जिसे आप मानचित्र को स्वीकार करने की आवश्यकता कहते हैं, लेकिन उसे संपादित करने की आवश्यकता नहीं है।

मैं जोश बलोच के प्रभावी जावा की जांच करने का सुझाव देता हूं , जो अपरिवर्तनीय वस्तुओं (थ्रेड सुरक्षा सहित) की कुछ बहुत अच्छी विशेषताओं को सूचीबद्ध करता है।


3

जब आप एक समारोह है यह उपयोगी हो सकता है कि रिटर्न एक immutable collectionऔर कुछ स्थिति में कोई डेटा लौटने की तो बजाय वापस जाने के लिए nullआप लौट सकते हैंemptyMap()

यह आपके कोड को आसान बनाता है और रोकता है NullPointerException


3

अधिकांश समय हम constructorएक नया बनाने के लिए उपयोग करते हैं empty map। लेकिन Collections methodsएक empty mapउपयोग बनाने के लिए कुछ लाभ प्रदान करते हैंstatic method java.util.Collections.emptyMap()

  1. वे अधिक संक्षिप्त हैं क्योंकि आपको संग्रह के सामान्य प्रकार को स्पष्ट रूप से टाइप करने की आवश्यकता नहीं है - यह आमतौर पर विधि कॉल के संदर्भ से अनुमान लगाया गया है।

  2. वे अधिक कुशल हैं क्योंकि वे नई वस्तुओं को बनाने से परेशान नहीं होते हैं; वे सिर्फ एक मौजूदा खाली और अपरिवर्तनीय वस्तु का फिर से उपयोग करते हैं। यह प्रभाव आम तौर पर बहुत मामूली होता है, लेकिन यह कभी-कभार (अच्छी तरह से, शायद ही कभी) महत्वपूर्ण होता है।


2

मुझे एक अपरिवर्तनीय खाली संग्रह क्यों चाहिए? मुद्दा क्या है?

उसी कारण से आप Collections.unmodifiableMap()किसी बिंदु पर उपयोग करेंगे । यदि आप उपयोगकर्ता को संशोधित करने का प्रयास करते हैं तो आप एक मानचित्र उदाहरण वापस करना चाहते हैं जो एक अपवाद फेंकता है। यह सिर्फ एक विशेष मामला है: खाली नक्शा।


1

मुझे एक अपरिवर्तनीय खाली संग्रह क्यों चाहिए? मुद्दा क्या है?

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.