java - तहस - भारत का नक्शा




क्या किसी ImmutableMap या मैप को वापस करना बेहतर है? (6)

दूसरी ओर, अगर मैं इसे इस तरह छोड़ दूंगा, तो अन्य डेवलपर्स इस तथ्य को याद कर सकते हैं कि यह ऑब्जेक्ट अपरिवर्तनीय है।

आपको इस बात का उल्लेख करना चाहिए कि javadocs में। डेवलपर्स उन्हें पढ़ते हैं, आप जानते हैं।

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

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

ध्यान दें, हालांकि, केवल Map ही अपरिवर्तनीय होगा, न कि इसमें मौजूद वस्तुएँ।

मान लीजिए कि मैं एक विधि लिख रहा हूं जो एक Map वापस करना चाहिए। उदाहरण के लिए:

public Map<String, Integer> foo() {
  return new HashMap<String, Integer>();
}

कुछ समय के लिए इसके बारे में सोचने के बाद, मैंने फैसला किया है कि इस मैप को बनाते समय इसे संशोधित करने का कोई कारण नहीं है। इस प्रकार, मैं एक ImmutableMap वापस करना चाहता हूं।

public Map<String, Integer> foo() {
  return ImmutableMap.of();
}

क्या मुझे रिटर्न टाइप को जेनेरिक मैप के रूप में छोड़ना चाहिए, या क्या मुझे यह निर्दिष्ट करना चाहिए कि मैं एक इम्यूटेबल मैप लौटा रहा हूं?

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


यदि मैं इसे इस तरह छोड़ दूंगा, तो अन्य डेवलपर्स इस तथ्य को याद कर सकते हैं कि यह ऑब्जेक्ट अपरिवर्तनीय है

यह सच है, लेकिन अन्य डेवलपर्स को अपने कोड का परीक्षण करना चाहिए और यह सुनिश्चित करना चाहिए कि यह कवर किया गया है।

फिर भी आपके पास इसे हल करने के लिए 2 और विकल्प हैं:

  • जावदोक का उपयोग करें

    @return a immutable map
  • वर्णनात्मक विधि नाम का चयन करें

    public Map<String, Integer> getImmutableMap()
    public Map<String, Integer> getUnmodifiableEntries()

    एक ठोस उपयोग के मामले में आप बेहतर तरीके से नाम भी दे सकते हैं। उदाहरण के लिए

    public Map<String, Integer> getUnmodifiableCountByWords()

आप और क्या कर सकते हैं?!

आप वापसी कर सकते हैं

  • प्रतिलिपि

    private Map<String, Integer> myMap;
    
    public Map<String, Integer> foo() {
      return new HashMap<String, Integer>(myMap);
    }

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

  • CopyOnWriteMap

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

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

    इस दृष्टिकोण का उपयोग किया जाना चाहिए यदि आप उम्मीद करते हैं कि कुछ ग्राहक मानचित्र को संशोधित करेंगे।

    अफसोस की बात है कि जावा में ऐसा CopyOnWriteMap नहीं है। लेकिन हो सकता है कि आप किसी तीसरे पक्ष को खोज लें या उसे स्वयं लागू कर दें।

अंत में आपको यह ध्यान रखना चाहिए कि आपके नक्शे में तत्व अभी भी परिवर्तनशील हो सकते हैं।


आपके पास अपने रिटर्न प्रकार के रूप में ImmutableMap होना चाहिए। Map में वे विधियाँ शामिल हैं जो @deprecated (जैसे put ) के कार्यान्वयन द्वारा समर्थित नहीं हैं और @deprecated में @deprecated में चिह्नित हैं।

पदावनत विधियों का उपयोग करने पर एक संकलक चेतावनी होगी और अधिकांश आईडीई चेतावनी देगा जब लोग पदावनत विधियों का उपयोग करने का प्रयास करेंगे।

यह उन्नत चेतावनी आपके पहले संकेत के रूप में रनटाइम अपवाद रखने के लिए बेहतर है कि कुछ गलत है।


निश्चित रूप से एक ImmutableMap लौटाएँ, औचित्य:

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

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

public ImmutableMap<String, Integer> foo() {
    return ImmutableMap.copyOf(internalMap);
}

अमरूद हर बार नक्शे की नकल करेगा। वह धीमा है। लेकिन अगर ImmutableMap पहले से ही ImmutableMap , तो यह पूरी तरह से ठीक है।

यदि आपने अपनी श्रेणी को ImmutableMap को वापस करने के लिए प्रतिबंधित नहीं किया है, तो आप इसके बजाय Collections.unmodifiableMap वापस कर सकते हैं:

public Map<String, Integer> foo() {
    return Collections.unmodifiableMap(internalMap);
}

ध्यान दें कि यह मानचित्र में एक अपरिवर्तनीय दृश्य है । अगर internalMap बदलता है, तो Collections.unmodifiableMap(internalMap) की एक कॉपी की जाएगी। मैं अभी भी इसे पाने वालों के लिए पसंद करता हूं।


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

public Integer fooOf(String key) {
    return map.get(key);
}

यह एपीआई को बहुत तंग करता है। यदि मानचित्र वास्तव में आवश्यक है, तो यह प्रविष्टियों की एक धारा प्रदान करके एपीआई के ग्राहक तक छोड़ा जा सकता है:

public Stream<Map.Entry<String, Integer>> foos() {
    map.entrySet().stream()
}

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

public Optional<Integer> fooOf(String key) {
    return Optional.ofNullable(map.get(key));
}




immutable-collections