2008-11-19 14 views
9

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

+0

आप "बैकअप" से क्या मतलब है? आप का मतलब है कि आप एक और ऐरेलिस्ट बनाना चाहते हैं जिसमें मौजूदा ऐरेलिस्ट में क्या है? –

उत्तर

12

मुझे लगता है कि आपको अलग-अलग ऑब्जेक्ट्स .clone() की आवश्यकता है। ArrayList क्लोनिंग "गहरा" नहीं है; यह केवल वस्तु के संदर्भों को क्लोन करेगा।

-3

आप एक ऑब्जेक्ट लिख सकते हैं जो दो ArrayLists को लपेटता है। कुछ भी इसे लिखता है ताकि यह एक ही समय में डेटा जोड़ता है, हटाता है और संशोधित करता है।

1

ऐसा लगता है (यदि मैं आपके प्रश्न को सही तरीके से समझता हूं; यह थोड़ा कठिन है) जैसे कि आप उस डेटा की प्रतिलिपि नहीं बना रहे हैं जिसका आप अपने बैरे में अपने ऐरेलिस्ट में संदर्भ दे रहे हैं; आप संदर्भ की प्रतिलिपि बना रहे हैं।

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

4

इन सभी प्रक्रियाओं में उथली प्रतियां होती हैं। यदि आप सरणी में ऑब्जेक्ट्स के गुणों को बदल रहे हैं, तो दो सरणी में एक ही उदाहरण के संदर्भ हैं।

List org = new java.util.ArrayList(); 
org.add(instance) 
org.get(0).setValue("org val"); 
List copy = new java.util.ArrayList(org); 
org.get(0).setValue("new val"); 

copy.get(0).getValue()"new val" रूप में अच्छी तरह क्योंकि org.get(0) वापस आ जाएगी और copy.get(0) ठीक उसी उदाहरण लौट आते हैं। आपको इस तरह की एक गहरी प्रतिलिपि करना है:

List copy = new java.util.ArrayList(); 
for(Instance obj : org) { 
    copy.add(new Instance(obj)); // call to copy constructor 
} 
+0

धन्यवाद! मेरे पास ओपी के समान प्रश्न था, और आपने इसे पूरी तरह उत्तर दिया। DeepCopy बनाम शालो कॉपी! और वास्तव में एक गहरी प्रतिलिपि कैसे करें! –

15

आपका प्रश्न बहुत स्पष्ट नहीं है। यदि आप एक ArrayList क्लोन() क्लोन करते हैं, तो क्लोन को संशोधित नहीं किया जाएगा यदि आप मूल की सामग्री को बदलते हैं (यानी यदि आप तत्व जोड़ते हैं या हटाते हैं) लेकिन यह एक "उथली प्रतिलिपि" है, इसलिए यदि आप वास्तविक वस्तुओं को मूल में बदल देंगे क्लोन में भी बदला जा सकता है।

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

ArrayList backup = new ArrayList(); 
for (Object obj : data) 
    backup.add(obj.clone()); 
8

में जैसा कि मैंने data संभालने हूँ ArrayList आप बैकअप करना चाहता था का नाम है। यदि ऐसा है, तो आपको पता होना चाहिए कि cloneगहरा नहीं है - यह केवल उस ऑब्जेक्ट की एक प्रति बनाता है जिस पर इसे लागू किया जाता है, जो इस मामले में सूची है। यदि यह एक गहरा क्लोन था, तो यह नई सूची को वस्तुओं के क्लोन के साथ भर देगा।

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

कुछ कक्षाएं clone को गहराई से ओवरराइड कर सकती हैं, लेकिन सभी नहीं। आम तौर पर, ऐसा कुछ नहीं है जिस पर आप भरोसा कर सकते हैं। जावा संग्रह की बैकअप प्रति बनाते समय, या तो निहित वस्तुओं को क्लोन करना याद रखें, या केवल अपरिवर्तनीय वस्तुओं के संग्रह के साथ सौदा करें।

0

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

वास्तव में, मैं यह प्रयास नहीं किया है लेकिन आप शायद एक पाइप अंदर और बाहर क्रमानुसार करने ही सटीक समय ताकि आप स्मृति में 3 प्रतियां भंडारण नहीं कर रहे हैं (अगर यह एक विशाल संग्रह है) इस्तेमाल कर सकते हैं

-1

मैंने अभी तक यह कोशिश नहीं की है, लेकिन मुझे लगता है कि Collections.copy ऐसा करेगा।

[संपादित करें] अब, मैं करने की कोशिश की:

static String GetRandomString(int length) 
{ 
    UUID uuid = UUID.randomUUID(); 
    return uuid.toString().substring(0, length); 
} 

public static void main(String[] args) 
{ 
    ArrayList<String> al = new ArrayList<String>(20); 
    for (int i = 0; i < 10; i++) 
    { 
    al.add(GetRandomString(7)); 
    } 
    ArrayList<String> cloneArray = new ArrayList<String>(al); 
    Collections.copy(cloneArray, al); 
    System.out.println(al); 
    System.out.println(cloneArray); 
    for (int i = 9; i >= 0; i -= 2) 
    { 
    al.remove(i); 
    } 
    System.out.println(al); 
    System.out.println(cloneArray); 
} 
+0

यह मेरा मानना ​​है कि वास्तव में गहरी प्रतिलिपि नहीं दिखाती है क्योंकि ऐड/निकालने का ऑपरेशन मूल सूची में बदलाव नहीं करेगा। मैंने आपके कोड को आजमाया लेकिन सूची सामग्री को कस्टम क्लास के साथ बदल दिया और सामग्री को बदल दिया (उन्हें हटाने के बजाए), तो कॉपी की गई सूची भी बदल दी गई। – Nrj

+0

@ एनआरजे: आह, आप सही हैं, सूचियां स्वतंत्र हैं लेकिन फिर भी वही ऑब्जेक्ट्स (संदर्भ) को इंगित करती हैं, इसलिए यह अभी भी एक उथली प्रतिलिपि है। मेरा बुरा (हे, दो साल पहले, मैं जावा में बहुत अच्छा नहीं था! :-)) – PhiLho

3

निर्भर करता है कि तुम क्या जरूरत है। उथला प्रतिलिपि (सूची में आइटम मूल के समान के लिए संदर्भ):

ArrayList backup = new ArrayList(mylist.size()); 
backup.addAll(mylist); 

डीप कॉपी (आइटम प्रतियां भी कर रहे हैं):

ArrayList backup = new ArrayList(mylist.size()); 
for(Object o : mylist) { 
    backup.add(o.clone()); 
} 
संबंधित मुद्दे