2010-01-15 17 views
6

स्थिर प्रारंभिक unmodifiableCollection.get गारंटीकृत अपरिवर्तनीय है?स्थिर प्रारंभिक unmodifiableCollection.get गारंटीकृत अपरिवर्तनीय है?

के लिए:

स्थिर अंतिम मानचित्र foo = Collections.unmodifiableMap (नई HashMap());

क्या एकाधिक धागे विधि का उपयोग कर सकते हैं और समस्याओं में नहीं चल सकते हैं?

भी FOO में आइटम के माध्यम से हटा नहीं जोड़ा जा सकता /, क्या कैशिंग प्रयोजनों, आदि के लिए FOO की आंतरिक स्थिति को जोड़ तोड़ आंतरिक स्थिति तो FOO समवर्ती नहीं किया जा सकता किसी भी तरह से संशोधित किया गया है, तो से विधि प्राप्त रोक। यदि ऐसा है, तो जावा में असली अपरिवर्तनीय संग्रह कहां हैं?

+1

वास्तव में एक अच्छा सवाल है। 'WeakHashMap' सोचें - जो बिना बदले में बदल सकता है। एक्सेस-ऑर्डर मोड में 'LinkedHashMap' वही है। –

+0

(आप अपने प्रश्न शीर्षक को प्रश्न में बैनर करना चाहते हैं - बैनर अंधापन।) –

+0

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

उत्तर

-1

मैं किसी भी थ्रेडेड ऑपरेशन के लिए ConcurrentHashMap या हैशटेबल का उपयोग करने के लिए सुझाव दूंगा, दोनों थ्रेड-सुरक्षित हैं।

+0

कोई भी वोट डाउन पर है, लॉल। –

+1

हाँ, अपरिवर्तनीय डेटा के लिए समवर्ती संचालन का उपयोग करना शायद एक बुरा विचार है। –

0

जावा एसडीके में कोई वास्तविक अपरिवर्तनीय मानचित्र नहीं है। क्रिस द्वारा सुझाए गए सभी मानचित्र केवल थ्रेड सुरक्षित हैं। अपरिवर्तनीय मानचित्र अपरिवर्तनीय नहीं है, क्योंकि अंतर्निहित मानचित्र बदलकर ConcurrentModificationException भी होगा।

यदि आप वास्तव में अपरिवर्तनीय मानचित्र चाहते हैं, तो Google संग्रह/अमरूद से ImmutableMap का उपयोग करें।

-1

क्या लौटा हुआ नक्शा पर एक गेटर कुछ आंतरिक राज्य के साथ झुकाव होता है, जब तक ऑब्जेक्ट अपने अनुबंध का सम्मान करता है (जो एक नक्शा होना चाहिए जिसे संशोधित नहीं किया जा सकता है)। तो आपका सवाल "गलत पेड़ को भड़काना" है।

यदि आप मानचित्र पर स्वामित्व और नियंत्रण नहीं रखते हैं, तो आप UnmodifiableMap से सावधान रहना सही हैं। उदाहरण के लिए

Map<String,String> wrapped = new HashMap<String,String>(); 
wrapped.add("pig","oink"); 
Map<String,String> wrapper = Collections.unmodifiableMap(wrapped); 
System.out.println(wrapper.size()); 
wrapper.put("cow", "moo"); // throws exception 
wrapped.put("cow", "moo"); 
System.out.println(wrapper.size()); // d'oh! 
+0

"महत्वहीन" - सच नहीं! यह बहुत महत्वपूर्ण है कि कक्षा थ्रेड-सुरक्षित नहीं है और दो धागे एक दूसरे के ऊपर कदम उठा रहे हैं! –

+0

इसे फिर से पढ़ें, महोदय। "जब तक यह अपने अनुबंध का सम्मान करता है।" –

0

वास्तव में एक अच्छा सवाल है। WeakHashMap सोचें - जो उस पर बुलाए गए उत्परिवर्तन ऑपरेशन के बिना बदल सकता है। एक्सेस-ऑर्डर मोड में LinkedHashMap बहुत समान है।

HashMap राज्य के लिए एपीआई डॉक्स:

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

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

static final Map FOO = Collections.unmodifiableMap(new HashMap()); 

फिर FOO अपरिवर्तनीय हो जाएगा:

+0

श्रीमान/एमएस डाउनवॉटर: मेरे जवाब के साथ कुछ भी गलत है, या सिर्फ बदला? –

4

विशिष्ट उदाहरण को देखते हुए। इसमें कभी भी कोई तत्व नहीं होगा।के और अधिक सामान्य स्थिति को देखते हुए:

static final Map BAR = Collections.unmodifiableMap(getMap()); 

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

static final Map BAR = Collections.unmodifiableMap(new HashMap(getMap())); 

javadocs for HashMap मतलब है कि इतने लंबे समय के रूप में आप नक्शे के लिए कोई संरचनात्मक परिवर्तन करें, फिर इसे सुरक्षित यह समवर्ती उपयोग करने के लिए है, इसलिए इस किसी भी एक्सेसर्स के लिए सुरक्षित होना चाहिए जिसका आप उपयोग कर सकते हैं, जो विभिन्न सेट प्राप्त कर रहा है और उन पर फिर से चल रहा है और() को सुरक्षित होना चाहिए।

आप समवर्ती कक्षाओं का उपयोग कर सकते हैं, तो आप भी कर सकता है:

static final Map BAR = Collections.unmodifiableMap(new ConcurrentHashMap(getMap()); 

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

+0

क्या होगा यदि मैं कहूं, 'बार' पर फिर से शुरू करना चाहते हैं? –

+0

@ टॉम: जैसा कि आप अपने उत्तर में उल्लेख करते हैं, और अब मैं अपने में उल्लेख करता हूं ;-), मानचित्र पर पुनरावृत्ति करना प्राप्त करने के रूप में सुरक्षित होना चाहिए। –

+0

लेकिन आप 'ConcurrentHashMap' और' निर्दिष्ट अनिश्चित कार्यान्वयन के मानचित्र के बारे में बात कर रहे हैं। –

2

ध्वनि की स्थिति में जैसे कि मैं एक विज्ञापन स्प्री पर हूं, Google Immutable Collections का उपयोग करें और इसके साथ किया जाए।

+0

आप बिना किसी कारण के निर्भरता क्यों पेश करेंगे? –

+0

क्यों किसी और के पास पहले से ही अपरिवर्तनीयता सुनिश्चित करने के लिए बाधाओं से कूदें? – Carl

+3

टॉम, कुछ लोगों के पास 'सार्वजनिक स्थैतिक अंतिम मानचित्र एमएपी = ImmutableMap के लिए सिर्फ एक स्टाइलिस्ट वरीयता है।(foo1, bar1, foo2, bar2); '' '' स्थिर स्थिर अंतिम मानचित्र एमएपी = initMap(); निजी स्थैतिक मानचित्र initMap() {मानचित्र मानचित्र = नया हैश मैप (); map.put (foo1, bar1); map.put (foo2, bar2); वापसी संग्रह .unmodifiableMap (मानचित्र); } '। –

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