जावा अपरिवर्तनीय संग्रह


115

से जावा 1.6 संग्रह फ्रेमवर्क प्रलेखन :

ऐसे संग्रह जो किसी भी संशोधन कार्यों (जैसे add, removeऔर clear) का समर्थन नहीं करते हैं , को अपरिवर्तनीय कहा जाता है । [...] ऐसे संग्रह जो अतिरिक्त गारंटी देते हैं कि संग्रह वस्तु में कोई परिवर्तन कभी दिखाई नहीं देगा, को अपरिवर्तनीय कहा जाता है ।

दूसरा मानदंड मुझे थोड़ा भ्रमित करता है। यह देखते हुए कि पहला संग्रह असंदिग्ध है, और यह मानते हुए कि मूल संग्रह संदर्भ को हटा दिया गया है, दूसरी पंक्ति में संदर्भित किए गए परिवर्तन क्या हैं? क्या यह संग्रह में रखे गए तत्वों यानी तत्वों की स्थिति में बदलाव का जिक्र है?

दूसरा प्रश्न:
संग्रहणीय होने के लिए, कोई व्यक्ति अतिरिक्त ग्वारंटियों को प्रदान करने के बारे में कैसे बताता है? यदि संग्रह में किसी तत्व की स्थिति को थ्रेड द्वारा अद्यतन किया जाता है, तो क्या यह अपरिवर्तनीयता के लिए पर्याप्त है कि राज्य में वे अपडेट अपरिवर्तनीय संग्रह को पकड़े हुए थ्रेड पर दिखाई नहीं दे रहे हैं?

संग्रह अपरिवर्तनीय होने के लिए, कोई व्यक्ति अतिरिक्त गारंटी प्रदान करने के बारे में कैसे बताता है?


सामान्य तौर पर (विशेष रूप से कार्यात्मक भाषाओं में), अपरिवर्तनीय (उर्फ लगातार) संग्रह इस अर्थ में बदल सकता है कि आप इस संग्रह की नई स्थिति प्राप्त कर सकते हैं, लेकिन साथ ही पुराना राज्य अभी भी अन्य लिंक से उपलब्ध होगा। उदाहरण के लिए, newCol = oldCol.add("element")नए संग्रह का उत्पादन करेगा जो 1 और तत्व के साथ पुराने की प्रतिलिपि है, और oldColइच्छा के सभी संदर्भ अभी भी उसी अपरिवर्तित पुराने संग्रह को इंगित करेंगे।
दोस्त

जवाबों:


154

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

अपरिवर्तनीय संग्रह को बिल्कुल नहीं बदला जा सकता है - वे दूसरे संग्रह को लपेटते नहीं हैं - उनके पास अपने तत्व हैं।

यहां अमरूद का एक उद्धरण दिया गया है ImmutableList

इसके विपरीत Collections.unmodifiableList(java.util.List<? extends T>), जो एक अलग संग्रह का एक दृश्य है जो अभी भी बदल सकता है, एक उदाहरण का ImmutableListअपना निजी डेटा होता है और यह कभी नहीं बदलेगा।

इसलिए, मूल रूप से, एक उत्परिवर्तनीय संग्रह से एक अपरिवर्तनीय संग्रह प्राप्त करने के लिए, आपको इसके तत्वों को नए संग्रह में कॉपी करना होगा, और सभी ऑपरेशनों को अस्वीकार करना होगा।


@ भास्कर - मेरा आखिरी पैराग्राफ देखिए।
बूझो

1
यदि संग्रह को किसी अन्य संग्रहणीय संग्रह के अंदर लपेटा जाता है, तो उसके पास कोई अन्य संदर्भ नहीं होता है, तो क्या संग्रहणीय संग्रह का bahaviour वास्तव में एक अपरिवर्तनीय संग्रह के समान है?
भास्कर

1
@Bozho, यदि बैकिंग संग्रह का संदर्भ नहीं दिया गया है, और केवल संग्रहणीय संग्रह आवरण संदर्भ प्रदान नहीं किया गया है, तो ऐसा कोई तरीका नहीं है जिससे आप इसे बदल सकें। फिर आप यह क्यों कहते हैं "आप निश्चित नहीं हो सकते"? क्या यह ऐसे परिदृश्य की ओर इशारा करता है, जहां कुछ थ्रेड या किसी तरह से इसे संशोधित किया जाता है क्योंकि बैकिंग संग्रह परिवर्तनीय है?
एकेएस

@AK: जब एक संग्रह में लपेटा जाता है unmodifiableList, तो कोड जो केवल उस सूची का एक संदर्भ प्राप्त करता है, उसे संशोधित करने में सक्षम नहीं होगा, लेकिन कोई भी कोड जिसमें मूल सूची का संदर्भ था और आवरण बनने से पहले इसे संशोधित कर सकता है बाद में ऐसा करने में सक्षम हो। यदि मूल सूची बनाने वाला कोड जानता है कि उसके पास मौजूद हर संदर्भ के साथ क्या हुआ है, और जानता है कि उनमें से कोई भी कोड के हाथों में नहीं आएगा जो सूची को संशोधित कर सकता है, तो यह जान सकता है कि सूची कभी नहीं होगी संशोधित। यदि संदर्भ बाहरी कोड से प्राप्त किया गया था, लेकिन ...
सुपर डिकैट

... इसका कोई तरीका नहीं है unmodifiableList, न ही कोई कोड जो इसका उपयोग करता है, यह जानने के लिए कि लिपटे हुए संग्रह में बदलाव हो सकता है या नहीं।
सुपरकैट

86

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

जैसे

List<String> strings = new ArrayList<String>();
List<String> unmodifiable = Collections.unmodifiableList(strings);
unmodifiable.add("New string"); // will fail at runtime
strings.add("Aha!"); // will succeed
System.out.println(unmodifiable);

1
विभिन्न कारणों से, यदि कोई हो, संग्रह में एक परिवर्तन ला सकता है जो कि अपरिहार्य है, बशर्ते कि मूल संग्रह संदर्भ को अंतर्निहित संग्रह को संशोधित करने के लिए उपयोग नहीं किया जाता है?
भास्कर

21
Collection<String> c1 = new ArrayList<String>();
c1.add("foo");
Collection<String> c2 = Collections.unmodifiableList(c1);

c1है परिवर्तनशील (यानी न unmodifiable है और न ही अपरिवर्तनीय )।
c2है unmodifiable : वह खुद को बदला नहीं जा सकता, लेकिन बाद में अगर मैं बदल c1तो यह है कि परिवर्तन में दिखाई नहीं देंगे c2

इसका कारण यह है कि c2बस एक आवरण के आसपास है c1और वास्तव में एक स्वतंत्र प्रति नहीं है। अमरूद ImmutableListइंटरफ़ेस और कुछ कार्यान्वयन प्रदान करता है । वे वास्तव में इनपुट की एक प्रति बनाकर काम करते हैं (जब तक कि इनपुट अपने आप में एक अपरिवर्तनीय संग्रह न हो)।

आपके दूसरे प्रश्न के बारे में:

किसी संग्रह की परस्परता / अपरिवर्तनीयता उसमें निहित वस्तुओं की परस्परता / अपरिवर्तनीयता पर निर्भर नहीं करती है। एक संग्रह में निहित एक वस्तु को संशोधित करना इस विवरण के लिए "संग्रह के संशोधन" के रूप में नहीं गिना जाता है। बेशक अगर आपको एक अपरिवर्तनीय संग्रह की आवश्यकता है, तो आप आमतौर पर यह भी चाहते हैं कि इसमें अपरिवर्तनीय वस्तुएँ शामिल हों।


2
@ जॉन: नहीं, यह नहीं है। कम से कम ओपी द्वारा बताई गई परिभाषा के अनुसार नहीं।
Joachim Sauer

@ जॉन, वास्तव में? मैं ऐसा नहीं सोचूंगा, क्योंकि c1 का उपयोग करते हुए, मैं अभी भी इसमें तत्व जोड़ सकता हूं, और यह जोड़ c2 को दिखाई देगा। क्या इसका मतलब यह नहीं है कि अपरिवर्तनीय नहीं है?
भास्कर

वैसे मुझे लगता है कि अगर c1 बच सकता है तो यह अपरिवर्तनीय नहीं होगा, लेकिन संग्रह के भीतर अपरिवर्तनीयता भी सामग्री को संदर्भित करती है। मैं java.util के अनमॉडिफ़ायलेबल का उल्लेख करने के बारे में अधिक था। डीटेट
जॉन विन्ट

1
@Vint: "अगर c1नहीं बचता है" एक ऐसा विचार नहीं है जो विनिर्देश में कहीं भी प्रतिष्ठित है। मेरी राय में, यदि आप संग्रह को इस तरह से उपयोग कर सकते हैं जो इसे गैर-अपरिवर्तनीय बनाता है, तो आपको हमेशा इसे गैर-अपरिवर्तनीय मानना चाहिए ।
जोआचिम सॉयर

1
मुझे परिभाषा उद्धृत करने दें: "संग्रह जो अतिरिक्त गारंटी देता है ..." (जोर मेरा)। Collection.unmodifiableList() इसकी गारंटी नहीं दे सकते , क्योंकि यह गारंटी नहीं दे सकता है कि इसका तर्क बच नहीं सकता है। अमरूद ImmutableList.of हमेशा एक अपरिवर्तनीय उत्पादन करता है List, भले ही आप इसके तर्कों से बचने दें।
जोचिम सॉर

17

अब java 9 में Immutable List, Set, Map और Map.Entry के कारखाने के तरीके हैं।

जावा एसई 8 और पहले के संस्करणों में, हम संग्रहणीय श्रेणी की उपयोगिता विधियों का उपयोग कर सकते हैं जैसे कि अपरिवर्तनीय संग्रह वस्तुएं बनाने के लिए अनमॉडिफ़ैटेबलएक्सएक्सएक्सएक्सएक्स।

हालाँकि ये Collections.unmodifiableXXX तरीके बहुत थकाऊ और क्रियात्मक दृष्टिकोण हैं। उन कमियों को दूर करने के लिए, ओरेकल कॉर्प ने लिस्ट, सेट और मैप इंटरफेस में कुछ उपयोगी तरीके जोड़े हैं।

अब java 9 में: - सूची और सेट इंटरफेस में नीचे दिखाए गए अनुसार खाली या खाली-खाली सूची या सेट ऑब्जेक्ट बनाने के लिए "()" तरीके हैं:

खाली सूची उदाहरण

List immutableList = List.of();

गैर-रिक्त सूची उदाहरण

List immutableList = List.of("one","two","three");

2
और जावा 10 में List.copyOfऔर Set.copyOfजोड़ दिए गए हैं जो किसी सूची / सेट की एक अप्रमाणिक प्रतिलिपि बनाने की अनुमति देते हैं, या दिए गए संग्रह को वापस करते हैं यदि यह पहले से ही अपरिवर्तनीय है, तो JDK-8191517
Marcono1234

6

मेरा मानना ​​है कि यहाँ पर यह है कि भले ही कोई संग्रह असम्बद्ध हो, लेकिन यह सुनिश्चित नहीं करता है कि यह बदल नहीं सकता है। उदाहरण के लिए एक संग्रह लें जो तत्वों को दर्शाता है यदि वे बहुत पुराने हैं। अचूक का अर्थ सिर्फ इतना है कि संदर्भ को धारण करने वाली वस्तु इसे बदल नहीं सकती है, न कि यह कि यह बदल नहीं सकती है। इसका एक सच्चा उदाहरण Collections.unmodifiableListविधि है। यह एक सूची का एक अपरिवर्तनीय दृश्य देता है। सूची संदर्भ जो इस पद्धति में पारित किया गया था वह अभी भी परिवर्तनीय है और इसलिए सूची को उस संदर्भ के किसी भी धारक द्वारा संशोधित किया जा सकता है। इसका परिणाम समवर्ती माॅडिफिकेशन अपवाद और अन्य खराब चीजें हो सकती हैं।

अपरिवर्तनीय, इसका मतलब है कि किसी भी तरह से संग्रह को नहीं बदला जा सकता है।

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


अच्छा था!! इसलिए अगर मैं अनमॉडिफ़ेबल कलेक्शन पर एक रैपर बनाता हूं और मॉडिफाइड कलेक्शन रेफरेंस को प्राइवेट बनाता हूं तो मुझे यकीन है कि यह अपरिवर्तनीय है। सही?
एकेएस

अगर मैं आपको सवाल समझ रहा हूं, तो जवाब नहीं है। Unmodifiable लपेटकर संग्रह को unmodifiableListसंशोधित करने के लिए इसे होने से बचाने के लिए कुछ भी नहीं करता है। यदि आप इस का उपयोग करना चाहते हैं ImmutableList
जॉन बी

0

Pure4J समर्थन करता है कि आप क्या हैं, दो तरह से।

सबसे पहले, यह एक @ImmutableValueएनोटेशन प्रदान करता है , ताकि आप एक वर्ग को एनोटेट कह सकें कि यह अपरिवर्तनीय है। एक मावेन प्लगइन है जो आपको यह जांचने की अनुमति देता है कि आपका कोड वास्तव में अपरिवर्तनीय है ( finalआदि का उपयोग )।

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

डिस्क्लेमर: मैं इसका डेवलपर हूं

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