سؤال

ولدي بعض البيانات المخزنة كما ArrayList. وعندما أريد أن النسخ الاحتياطي هذه البيانات، جافا الصرقية كائنين إلى الأبد. مما يعني عندما أقوم بتغيير القيم في ArrayList البيانات هذه التغييرات تأتي إلى النسخ الاحتياطي. حاولت نسخ القيم من البيانات بشكل منفصل للنسخ الاحتياطي في الحلقة، حاولت استخدام طريقة data.clone() - لا شيء يساعد

هل كانت مفيدة؟

المحلول

وأعتقد أنك تحتاج إلى .clone() الكائنات الفردية. استنساخ ArrayList ليست "العميق". فإنه سيتم استنساخ فقط ما يشير إلى الكائن.

نصائح أخرى

وسؤالك ليس واضحا جدا. إذا كنت استنساخ () لArrayList، لن يتم تعديل استنساخ إذا قمت بتغيير محتويات الأصلي (أي إذا قمت بإضافة أو إزالة عناصر) لكنه "نسخة الضحلة" حتى إذا قمت بتغيير الكائنات الفعلية في الأصل أنها سوف كما أن تتغير في استنساخ.

إذا كنت تريد أن تجعل "نسخة العميق"، بحيث تغييرات على الكائنات الفعلية لن يؤثر على النسخ الاحتياطي منهم في استنساخ، فأنت بحاجة إلى إنشاء ArrayList جديد ثم تذهب من خلال نسخة أصلية واحدة ولكل العنصر، استنساخ ذلك في واحدة جديدة. كما هو الحال في

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

وأفترض data هو اسم ArrayList أردت النسخ الاحتياطي. إذا كان الأمر كذلك، يجب أن نعرف أن clone ليس <م> العميقة - أنه يخلق فقط نسخة من الكائن الذي يتم استدعاؤه، والذي هو في هذه الحالة القائمة. لو كان استنساخ العميق، فإنه ملء القائمة الجديدة مع استنساخ الكائنات في ذلك.

ولأنها ليست عميقة، إذا قمت بتغيير الكائنات تحتوي القائمة، ثم قائمة النسخ الاحتياطي سوف تظهر هذه التغييرات أيضا، حيث انها تحتوي على نفس الكائنات. المرة الوحيدة التي سوف لا ترى التغييرات في النسخة الاحتياطية بعد تغيير قائمة "الحالية" هو عند إضافة أو إزالة الكائنات من القائمة الحالية.

وبعض الطبقات قد تتجاوز clone أن تكون عميقة، ولكن ليس كل شيء. بشكل عام، انها ليست شيئا يمكنك الاعتماد عليها. عند إنشاء نسخة احتياطية من مجموعات جافا، تذكر إما استنساخ الكائنات الواردة أيضا، أو لا نتعامل الا مع مجموعات من الأجسام الثابتة.

وجميع هذه العمليات عمل نسخ الضحلة. إذا كنت تغيير خصائص الكائنات في مجموعة، المصفوفات لهما كل ما يشير إلى نفس المثيل.

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
}

ويعتمد على ما تحتاج إليه. نسخة الضحلة (البنود في القائمة هي ما يشير إلى نفسه كما في النص الأصلي):

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

ونسخة العميقة (البنود هي نسخ أيضا):

ArrayList backup = new ArrayList(mylist.size());
for(Object o : mylist) {
    backup.add(o.clone());
}

وهذا يبدو و(إذا كنت تفسير سؤالك بشكل صحيح، انها صعبة قليلا) وكأنك لا نسخ البيانات التي كنت في اشارة الى ArrayList في لالاحتياطية الخاصة بك. كنت نسخ المرجع.

وانه من الصعب القول بالضبط كيفية حل مشكلتك دون معرفة ما هو نوع البيانات التي كنت تخزين / النسخ الاحتياطي، ولكن فقط أن تتأكد من أنك نسخ العناصر من البيانات الواردة في ArrayList. وهذا يعني، من بين أمور أخرى، على أن تفعل أشياء مثل إجراء استنساخ () على عناصر القائمة، ولكن ليس على ArrayList (لأن ذلك سوف إنشاء قائمة جديدة المستنسخة مع نسخ من كل ما يشير إلى نفس الأشياء).

وفيما يتعلق بمشكلة الاستنساخ، وبمجرد أن تحل هذا عن طريق تسلسل المجموعة بأكملها إلى سلسلة ثم تسلسل مرة أخرى للخروج الى وجوه جديدة. هذا يفرض لك لجعل كل ما تبذلونه من الأشياء تسلسل واتخاذ عندما تريد كائنين حقا مرجع كائن ثالث واحد، ولكنه يمكن أن يكون هناك توازن جيد من البساطة وفائدة.

في الواقع، لم أحاول ذلك ولكن ربما كنت يمكن استخدام الأنابيب لتسلسل الدخول والخروج في نفس الوقت بالضبط بحيث انك لا تخزين 3 نسخ في الذاكرة (في حالة انها مجموعة ضخمة)

وهنا تعمل بشكل كامل الطبقة ArrayList النسخ الاحتياطي الذي يتحقق إذا كان ArrayList موجود بالفعل. أساسا انها مجرد لحلقة ركوب الدراجات من خلال قائمة ويدويا إضافتها إلى القائمة الجديدة.

import java.util.ArrayList;

public class Snapshot {
    private ArrayList<Integer> dataBackup;

    public Snapshot(ArrayList<Integer> data)
    {
        dataBackup = new ArrayList<Integer>();
        for(int i = 0; i < data.size(); i++)
        {
            dataBackup.add(data.get(i));
        }
    }

    public ArrayList<Integer> restore()
    {
        return dataBackup;
    }

    public static void main(String[] args)
    {
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);

        Snapshot snap = new Snapshot(list);

        list.set(0, 3);
        list = snap.restore();

        System.out.println(list); // Should output [1, 2]

        list.add(4);
        list = snap.restore();

        System.out.println(list); // Should output [1, 2]
    }
}

ولم أحاول حتى الآن، ولكن أعتقد أن 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);
}

هل يمكن كتابة كائن التي يلتف اثنين ArrayLists. أي شيء كتابته بحيث يضيف، يزيل، ويعدل البيانات في كلا في نفس الوقت.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top