문제

몇 가지 데이터가 저장되어 있습니다 ArrayList. 그리고이 데이터를 백업하고 싶을 때 Java는 두 개의 객체를 영원히 바운드합니다. 이는 데이터의 값을 변경할 때를 의미합니다 ArrayList 이 변경 사항은 백업됩니다. 루프에서 데이터에서 값을 별도로 복사하려고했는데 방법을 사용하려고했습니다. data.clone() - 아무것도 도움이되지 않습니다.

도움이 되었습니까?

해결책

나는 당신이 필요하다고 생각합니다 .clone() 개별 대상. 복제 ArrayList "깊은"것이 아닙니다. 물체에 대한 참조 만 복제합니다.

다른 팁

귀하의 질문은 분명하지 않습니다. 원본의 내용을 변경하는 경우 (예 : 요소를 추가하거나 제거하는 경우) 배열 목록을 복제하는 경우 클론이 수정되지 않지만 "얕은 사본"이므로 원본의 실제 객체를 변경하면 원본입니다. 클론에서도 변경됩니다.

"딥 카피"를 만들려면 실제 객체의 변경 사항이 클론의 백업에 영향을 미치지 않으면 새 배열리스트를 작성한 다음 원래 요소를 통해 각 요소를 통해 복제해야합니다. 새로운 것입니다. 에서와 같이

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

나는 가정하고있다 data 이름입니다 ArrayList 백업하고 싶었습니다. 그렇다면, 당신은 그것을 알아야합니다 clone 아니다 깊은 - 호출 된 객체의 사본 만 생성합니다.이 경우 목록입니다. 그것이 깊은 클론이라면, 새 목록에 물체의 클론으로 채워집니다.

깊지 않기 때문에 목록에 포함 된 객체를 변경하면 백업 목록에 동일한 개체가 포함되어 있기 때문에 이러한 변경 사항도 표시됩니다. "현재"목록을 변경 한 후 백업의 변경 사항이 표시되지 않는 유일한 시간은 현재 목록에서 객체를 추가하거나 제거 할 때입니다.

일부 클래스가 무시할 수 있습니다 clone 깊지는 않지만 전부는 아닙니다. 일반적으로, 그것은 당신이 의존 할 수있는 것이 아닙니다. Java 컬렉션의 백업 사본을 만들 때 포함 된 물체를 복제하거나 불변의 개체 모음 만 처리해야합니다.

이 모든 과정은 얕은 사본을 만듭니다. 배열에있는 객체의 속성을 변경하는 경우 두 배열은 동일한 인스턴스에 대한 참조를 갖습니다.

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에는 그렇지 않습니다 (동일한 개체에 대한 참조 사본으로 새로운 클로닝 된 목록이 만들어지기 때문입니다).

복제 문제와 관련하여 전체 컬렉션을 문자열로 직렬화하여이를 해결 한 다음 새 개체로 다시 직렬화하여 해결했습니다. 이를 통해 모든 객체를 직렬화 할 수있게하고 두 개체가 실제로 단일 세 번째 객체를 참조하려는 경우, 단순성과 유용성의 균형이 잘 될 수 있습니다.

실제로, 나는 이것을 시도하지 않았지만 아마도 파이프를 사용하여 정확히 같은 시간에 직렬화 및 아웃을 할 수 있으므로 메모리에 3 개의 사본을 저장하지 않을 수 있습니다 (거대한 컬렉션 인 경우).

다음은 배열리스트가 이미 존재하는지 확인하는 완전히 작동하는 ArrayList 백업 클래스입니다. 기본적으로 그것은 목록을 통해 순환하는 for-loop 일뿐입니다. 새 목록에 수동으로 추가합니다.

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);
}

두 개의 배열리스트를 감싸는 객체를 쓸 수 있습니다. 무엇이든 모든 것이 추가, 제거 및 동시에 데이터를 수정하도록 작성합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top