जावा में एक मानचित्र की उथली प्रतिलिपि


106

जैसा कि मैं इसे समझता हूं, Mapजावा में एक उथले कॉपी बनाने के लिए कुछ तरीके हैं (शायद दूसरों के साथ भी) :

Map<String, Object> data = new HashMap<String, Object>();
Map<String, Object> shallowCopy;

// first way
shallowCopy = new HashMap<String, Object>(data);

// second way
shallowCopy = (Map<String, Object>) ((HashMap<String, Object>) data).clone();

क्या एक तरीका दूसरे पर पसंद किया जाता है, और यदि हां, तो क्यों?

एक बात ध्यान देने योग्य है कि दूसरा तरीका "अनियंत्रित कास्ट" चेतावनी देता है। तो आपको इसके @SuppressWarnings("unchecked")आसपास जाने के लिए जोड़ना होगा, जो थोड़ा परेशान है (नीचे देखें)।

@SuppressWarnings("unchecked")
public Map<String, Object> getDataAsMap() {
    // return a shallow copy of the data map
    return (Map<String, Object>) ((HashMap<String, Object>) data).clone();
}

जावा के नए संस्करणों में (जावा 10 के बाद से, सटीक होने के लिए) आप Map.copyOf static factory पद्धति का उपयोग कर सकते हैं । लेकिन ध्यान दें कि यह एक अविश्वसनीय नक्शा देता है!
ओलेकांद्र प्य्रोहोव

जवाबों:


106

कॉपी कंस्ट्रक्टर का उपयोग करके कॉपी करना हमेशा बेहतर होता है। clone()जावा में टूटा हुआ है (एसओ देखें: क्लोन विधि को कैसे ठीक से ओवरराइड करें? )।

डिजाइन पर जोश बलोच - क्लोनिंग बनाम कॉपी कंस्ट्रक्टर

यदि आपने मेरी पुस्तक में क्लोनिंग के बारे में आइटम पढ़ा है, खासकर यदि आप लाइनों के बीच पढ़ते हैं, तो आपको पता चल जाएगा कि मुझे लगता cloneहै कि गहराई से टूट गया है। [...] यह एक शर्म की बात है Cloneableजो टूट गया है, लेकिन ऐसा होता है।

बलोच (जिस तरह से, कलेक्शन फ्रेमवर्क को डिजाइन और कार्यान्वित किया गया था) ने यह कहते हुए और भी आगे बढ़ा दिया कि वह केवल clone()"सिर्फ इसलिए लोगों को उम्मीद करता है" विधि प्रदान करता है । वह वास्तव में इसका उपयोग करने की सलाह नहीं देता है।


मुझे लगता है कि अधिक दिलचस्प बहस यह है कि क्या एक कॉपी निर्माता कॉपी फैक्ट्री से बेहतर है, लेकिन यह पूरी तरह से एक अलग चर्चा है।


1
हां, यह पुस्तक के मेरे पसंदीदा भागों में से एक है।
पॉलीजेन लुब्रीकेंट

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

4
प्रतिलिपि ctor का उपयोग नहीं करने के लिए आपको यह जानना होगा कि आप मानचित्र के किस कार्यान्वयन की नकल कर रहे हैं? एक अनावश्यक सीमा की तरह लगता है।
जौन-हसन

"क्योंकि वह केवल क्लोन () विधि प्रदान करता है" क्योंकि लोग इसकी उम्मीद करते हैं "- स्रोत?
एडम पार्किं

60

दोनों में से कोई भी: जिस कंस्ट्रक्टर का आप जिक्र कर रहे हैं , वह मैप के हैशपैड कार्यान्वयन के लिए परिभाषित किया गया है , (साथ ही दूसरों के लिए भी) लेकिन मैप इंटरफेस के लिए ही नहीं (उदाहरण के लिए, मैप इंटरफेस के प्रदाता कार्यान्वयन पर विचार करें: आप उस कंस्ट्रक्टर को नहीं मिलेगा)।

दूसरी ओर, clone()विधि का उपयोग करना उचित नहीं है , जैसा कि जोश बलोच ने बताया है।

मानचित्र इंटरफ़ेस के संबंध में (और आपके प्रश्न का, जिसमें आप पूछते हैं कि मानचित्र की प्रतिलिपि कैसे बनाई जाए , न कि किसी हाशपैप की), आपको मानचित्र # putAll () का उपयोग करना चाहिए :

निर्दिष्ट नक्शे से इस मानचित्र (वैकल्पिक संचालन) तक सभी मैपिंग की प्रतियां। इस कॉल का प्रभाव निर्दिष्ट मानचित्र में कुंजी k से मान v तक प्रत्येक मैपिंग के लिए एक बार इस मानचित्र पर कॉल पुट (k, v) के बराबर है।

उदाहरण:

// HashMap here, but it works for every implementation of the Map interface
Map<String, Object> data = new HashMap<String, Object>();
Map<String, Object> shallowCopy = new HashMap<String, Object>();

shallowCopy.putAll(data);

2
तो फिर स्पष्ट करने के लिए: यदि आप जानते हैं कि एक कार्यान्वयन के लिए कॉपी कर रहे हैं Mapजिसकी एक कॉपी कंस्ट्रक्टर है तो कॉपी कंस्ट्रक्टर का उपयोग नहीं करने का कोई कारण नहीं है?
एडम पार्किन

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

1
यकीन है, हालांकि आम तौर पर मैं 2-लाइनर्स से बेहतर 1-लाइनर्स पसंद करता हूं। ;)
एडम पार्किन

11

इसके कार्यान्वयन को जाने बिना मानचित्र की प्रतिलिपि बनाएँ:

static final Map shallowCopy(final Map source) throws Exception {
    final Map newMap = source.getClass().newInstance();
    newMap.putAll(source);
    return newMap;
}

3
<K,V>टाइप सुरक्षा सुनिश्चित करने में मदद करने के लिए टाइप पैरामीटर जोड़ने पर विचार करें ।
बर्ट

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