मैं जावा में एक सामान्य सूची कैसे क्लोन कर सकता हूं?


155

मेरे पास ArrayList<String>एक कॉपी है जिसे मैं वापस करना चाहूंगा। ArrayListएक क्लोन विधि है जिसमें निम्नलिखित हस्ताक्षर हैं:

public Object clone()

इस विधि को कॉल करने के बाद, मैं लौटी हुई वस्तु को वापस कैसे डालूं ArrayList<String>?


16
नहीं, यह एक वैध प्रश्न है। जावा रनटाइम टाइप इरेज़र और सभी के साथ "ट्रू" जेनरिक का समर्थन नहीं करता है, इसलिए इस प्रकार के विवरण मुश्किल हो सकते हैं। इसके अलावा, क्लोन करने योग्य इंटरफ़ेस और Object.clone () विधि तंत्र समान रूप से भ्रमित है।
प्रोग्रामर

ठीक है, मैं ज्यादातर सी # करता हूं जहां यह वास्तव में आसान है। कृपया मुझे बताएं कि क्या आप चाहते हैं कि मैं इस प्रश्न से टिप्पणियों को हटा दूं।
एस्पो

1
आप टिप्पणी छोड़ सकते हैं। मुझे लगता है कि मेरे संपादन ने समझाया कि मुझे क्या परेशानी हो रही थी।
छिपकली का बिल

2
आपकी टिप्पणी ठीक है, अगर थोड़ा सा कृपालु। मुझे लगता है कि जावा डेवलपर्स के माध्यम से कूद करने के लिए बहुत सारे हुप्स हैं। .NET डेवलपर्स को मूर्खतापूर्ण प्रतीत होता है।
प्रोग्रामर

1
@ ऑस्कर, वह क्लोन करना चाहता है, न कि क्लोन कमांड को लागू करना। यह वही नहीं हो सकता है यह क्लोन वास्तव में क्लोन नहीं है। मुझे लगता है कि यह बात है। यह वास्तव में एक मुश्किल सवाल है।
राफा

जवाबों:


62
ArrayList newArrayList = (ArrayList) oldArrayList.clone();

43
यह स्ट्रिंग्स के लिए ठीक काम करेगा (जो कि सवाल पूछा गया है), लेकिन यह ध्यान देने योग्य है कि ArrayList.clone एक उथली प्रतिलिपि का प्रदर्शन करेगा, इसलिए यदि सूची में उत्परिवर्तित वस्तुएं थीं, तो उन्हें क्लोन नहीं किया जाएगा और एक को बदलना एक सूची में उस दूसरी सूची में भी एक बदल जाएगा।
pkaeding

49
आपको कुछ भी लेकिन विरासत कोड में कच्चे प्रकार का उपयोग करने से बचना चाहिए। आप बेहतर उपयोग कर रहे हैं ArrayList<String> newArrayList = (ArrayList<String>) oldArrayList.clone();
cdmckay

20
यह बहुत बुरा है ArrayList में एक #clone विधि है, लेकिन सूची ही नहीं है। आह।
रोजरपैक

12
संबंधित नहीं है, जबकि उस पर: बाईं ओर के List<String>बजाय का उपयोग करें ArrayList<String>। इस तरह से अधिकांश समय संग्रह का उपयोग किया जाना चाहिए।
क्रिस्टोफ रूसो

3
मैं एक ArrayList को डुप्लिकेट करने के लिए इस पद्धति का उपयोग नहीं कर सका। क्लोन () विधि को मान्यता नहीं दी गई थी।
जैक

318

आप क्लोन क्यों करना चाहेंगे? नई सूची बनाना आमतौर पर अधिक मायने रखता है।

List<String> strs;
...
List<String> newStrs = new ArrayList<>(strs);

काम हो गया।


17
आप नहीं जानते होंगे कि यह किस प्रकार की सूची है। यह एक लिंक्डलिस्ट, MyOwnCustomList या ArrayList का एक उपवर्ग हो सकता है, जिस स्थिति में एक ArrayList को नया बनाना गलत प्रकार होगा।
स्टीव कू

51
क्या मुझे परवाह है कि मूल सूची का उपयोग किस कार्यान्वयन में किया जाएगा? मैं शायद इस बात का ध्यान रखता हूं कि नई सूची के उपयोग पर कौन सा कार्यान्वयन हो
टॉम हॉकिन -

12
@Steve Kuo: हस्ताक्षर का ArrayList(Collection<? extends E> c)अर्थ है कि यह मायने नहीं रखता कि आप तर्क के रूप में किस प्रकार की सूची का उपयोग करते हैं।
cdmckay

3
मेरा मतलब है कि यह एक गहरी प्रतिलिपि नहीं है, क्या यह है?

4
@YekhezkelYovel नहीं, यह नहीं होगा।
टॉम हॉल्टिन -

19

यह वह कोड है जिसका मैं उपयोग करता हूं:

ArrayList copy = new ArrayList (original.size());
Collections.copy(copy, original);

आशा है कि आप के लिए उपयोगी है


3
और कच्चे प्रकारों के उपयोग से बचें .. इसलिए ArrayListउपयोग के बजायArrayList<YourObject>
milosmns

2
docs.oracle.com/javase/8/docs/api/java/util/… काम नहीं करता क्योंकि सूची आकार भिन्न हैं।
MLProgrammer-CiM

आप सिर्फ ArrayListकंस्ट्रक्टर के ओवरलोडिंग का उपयोग क्यों नहीं करेंगे ?
टॉम हॉकिन -

19

जावा 8 के साथ इसे एक स्ट्रीम के साथ क्लोन किया जा सकता है।

import static java.util.stream.Collectors.toList;

...

List<AnObject> clone = myList.stream().collect(toList());

सूची <AnObject> xy = new ArrayList <> (oldList) की तरह किया जा सकता है;
मिरज़ाक २५'१

1
यह एक गहरी नकल नहीं है, एक सूची के तत्वों में परिवर्तन दूसरे में देखा जा सकता है
इनचरा

2
जहां प्रश्न में यह निर्दिष्ट करता है कि एक गहरी प्रति की आवश्यकता है? धारणा यह है कि समान वस्तुओं वाले एक और संग्रह की आवश्यकता होती है। यदि आप गहरी प्रतिलिपि मार्ग से नीचे जाना चाहते हैं तो आप कीड़े के एक पूरे नए डिब्बे को खोल सकते हैं।
साइमन जेनकिंस

हालांकि, यह वास्तव में एक क्लोन नहीं है? एपीआई डॉक्स से "लौटी हुई सूची के प्रकार, परिवर्तनशीलता, क्रमबद्धता या थ्रेड-सुरक्षा पर कोई गारंटी नहीं है"। और, उनमें से एक नहीं चाहते हैं। toCollectionएक बेहतर विकल्प हो सकता है।
टॉम हॉल्टिन -

16

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


15

मुझे लगता है कि यह कलेक्शन एपीआई का उपयोग करके चाल करना चाहिए:

नोट : प्रतिलिपि विधि रेखीय समय में चलती है।

//assume oldList exists and has data in it.
List<String> newList = new ArrayList<String>();
Collections.copy(newList, oldList);

13
नए ArrayList <String> (oldList) का उपयोग क्यों न करें?
cdmckay

4
मेरा मानना ​​है कि यह काम नहीं करेगा, डॉक्टर से * गंतव्य सूची कम से कम तब तक होनी चाहिए जब तक स्रोत सूची। यदि यह लंबा है, तो गंतव्य सूची में शेष तत्व अप्रभावित हैं।
ग्रेग डोमिन

@GregDomjan नहीं कि मैं सहमत हूँ कि यह सबसे अच्छा तरीका है, लेकिन यह इसे करने का एक तरीका है। अपने मुद्दे के इर्द-गिर्द इसे पाने के लिए यह उतना ही सरल है: सूची <string> newList = new ArrayList <> (oldList.size ());
nckbrz

1
निश्चित नहीं है कि यह जावा 8 से संबंधित है, लेकिन आकार को निर्दिष्ट करते हुए भी, अभी भी एक अपवाद प्राप्त कर रहा है IndexOutOfBoundsException: गंतव्य.size () <source.size (): 0 <2 पर List<MySerializableObject> copyList = new ArrayList<>(mMySerializableObjects.size()); इसका उपयोग copyList.addAll(original);करना एक अच्छा विकल्प है
जीन बो

@GeneBo यह आकार निर्दिष्ट नहीं कर रहा है। यह क्षमता को निर्दिष्ट कर रहा है, जो एक बहुत अलग बात है। रहस्य intतर्कों की खुशी । मुझे नहीं पता कि आप अच्छे पुराने के बजाय इस अस्पष्ट स्थैतिक पद्धति का उपयोग क्यों करना चाहते हैं addAll
टॉम हॉकिन -

8

मुझे लगता है कि addAll का उपयोग करना ठीक काम करता है।

ArrayList<String> copy = new ArrayList<String>();
copy.addAll(original);

कोष्ठक का उपयोग जेनरिक सिंटैक्स के बजाय किया जाता है


5
यह स्ट्रिंग्स के लिए काम करेगा, लेकिन उत्परिवर्तित वस्तुओं के लिए नहीं। आप उन लोगों को भी क्लोन करना चाहते हैं।
jodonnell

हाँ, उनका प्रश्न तार के लिए है। और उसे जेनेरिक की समस्या है जो वास्तव में इस मामले में कास्टिंग सामान पसंद नहीं करते हैं।
Allain लालोंडे

इसके अलावा, ArrayList.clone केवल एक उथले क्लोन करेगा, इसलिए सूची में उत्परिवर्तित वस्तुओं को उस विधि का उपयोग करके क्लोन नहीं किया जाएगा।
pkaeding

यह ArrayList <String> btw होना चाहिए। इसके अलावा, आप शायद नए ArrayList <String> (मूल) का उपयोग करके बेहतर हैं क्योंकि यह कम लेखन और बस के रूप में स्पष्ट है।
cdmckay

4
सिर्फ उपयोग क्यों नहीं new ArrayList<String>(original)?
user102008

6

यदि आप चाहते हैं कि एक गेटर में सूची को वापस करने में सक्षम होने के लिए यह करना बेहतर होगा:

ImmutableList.copyOf(list);

4

एक सामान्य इंटरफ़ेस को क्लोन करने के लिए जैसे java.util.Listआपको इसे डालना होगा। यहाँ आप एक उदाहरण हैं:

List list = new ArrayList();
List list2 = ((List) ( (ArrayList) list).clone());

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

मुझे पता है कि यह उत्तर अंतिम उत्तर के करीब है, लेकिन मेरा उत्तर यह बताता है कि जब आप Listसामान्य माता-पिता के साथ काम कर रहे हों, तो वह सब कैसे करें- नहींArrayList


2
आप मान रहे हैं कि यह हमेशा एक ArrayList होगा जो सच नहीं है
jucardi

@JuanCarlosDiaz विल, यह सवाल पूछा गया है, यह ArrayList के बारे में था, इसलिए मैंने इसका जवाब ArrayList के लिए दिया :)
अहमद हम्दी

2

ArrayLists क्लोनिंग करते समय बहुत सावधान रहें। जावा में क्लोनिंग उथली है। इसका मतलब है कि यह केवल Arraylist को क्लोन करेगा और इसके सदस्यों को नहीं। इसलिए यदि आपके पास एक ArrayList X1 है और इसे X2 में क्लोन किया है तो X2 में कोई भी परिवर्तन X1 में प्रकट होगा और इसके विपरीत। जब आप क्लोन करते हैं तो आप केवल मूल में समान तत्वों के संकेत के साथ एक नया ArrayList उत्पन्न करेंगे।


2

यह भी काम करना चाहिए:

ArrayList<String> orig = new ArrayList<String>();
ArrayList<String> copy = (ArrayList<String>) orig.clone()

2
List<String> shallowClonedList = new ArrayList<>(listOfStrings);

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



1

मैं एक जावा पेशेवर नहीं हूं, लेकिन मुझे एक ही समस्या है और मैंने इस पद्धति से हल करने की कोशिश की। (यह माना जाता है कि टी में एक कॉपी कंस्ट्रक्टर है)।

 public static <T extends Object> List<T> clone(List<T> list) {
      try {
           List<T> c = list.getClass().newInstance();
           for(T t: list) {
             T copy = (T) t.getClass().getDeclaredConstructor(t.getclass()).newInstance(t);
             c.add(copy);
           }
           return c;
      } catch(Exception e) {
           throw new RuntimeException("List cloning unsupported",e);
      }
}

इस बात की कोई गारंटी नहीं है कि Listकार्यान्वयन वर्ग के पास सार्वजनिक नहीं-आर्ग निर्माता है। उदाहरण के लिए, Listएस रिटर्न Array.asList, List.ofया List.subListशायद नहीं।
टॉम हॉल्टिन -
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.