いくつかのデータをとして保存していArrayList
ます。そして、このデータをバックアップしたいとき、javaは2つのオブジェクトを永久にバインドします。つまり、データの値を変更すると、ArrayList
この変更がバックアップになります。データから値を個別にコピーしてループ内のバックアップにしようとしましたが、メソッドを使用しようとしましたが、data.clone()
何も役に立ちません。
10 に答える
あなたの質問はあまり明確ではありません。ArrayList を clone() した場合、元の内容を変更しても (要素を追加または削除した場合)、複製は変更されませんが、それは「浅いコピー」であるため、元の実際のオブジェクトを変更すると、クローンでも変更できます。
「ディープ コピー」を作成して、実際のオブジェクトへの変更がクローン内のそれらのバックアップに影響を与えないようにする場合は、新しい ArrayList を作成してから、元の ArrayList を調べ、要素ごとにクローンを作成する必要があります。それを新しいものにします。のように
ArrayList backup = new ArrayList();
for (Object obj : data)
backup.add(obj.clone());
.clone()
個々のオブジェクトが必要だと思います。の複製ArrayList
は「深い」ものではありません。オブジェクトへの参照を複製するだけです。
は、バックアップしたいdata
の名前だと思います。ArrayList
もしそうなら、それは深いclone
ものではないことを知っておくべきです- それは呼び出されたオブジェクトのコピーを作成するだけです。この場合はリストです。ディープ クローンの場合、新しいリストはその中のオブジェクトのクローンで埋められます。
深くないため、リストに含まれるオブジェクトを変更すると、同じオブジェクトが含まれているため、バックアップ リストにもそれらの変更が表示されます。「現在の」リストを変更した後にバックアップに変更が見られないのは、現在のリストにオブジェクトを追加または削除するときだけです。
一部のクラスはオーバーライドclone
して深くなる場合がありますが、すべてではありません。一般的に、それはあなたが信頼できるものではありません。Java コレクションのバックアップ コピーを作成するときは、含まれているオブジェクトも複製するか、不変オブジェクトのコレクションのみを処理することを忘れないでください。
これらのプロセスはすべて浅いコピーを作成します。配列内のオブジェクトのプロパティを変更する場合、2 つの配列は同じインスタンスへの参照を持ちます。
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 に含まれるデータの要素をコピーしていることを確認してください。これは、とりわけ、リストの要素に対して clone() を実行するなどのことを行うことを意味しますが、ArrayList に対しては実行しません (同じオブジェクトへの参照のコピーを含む新しいクローン リストが作成されるため)。
複製の問題に関しては、コレクション全体を文字列にシリアル化し、それをシリアル化して新しいオブジェクトに戻すことでこれを解決したことがあります。これにより、すべてのオブジェクトをシリアライズ可能にし、2 つのオブジェクトが 1 つの 3 番目のオブジェクトを実際に参照したい場合に実行する必要がありますが、単純さと有用性のかなり良いバランスになる可能性があります。
実際、私はこれを試したことはありませんが、パイプを使用して同時に正確にシリアル化して、3 つのコピーをメモリに格納しないようにすることができます (巨大なコレクションの場合)。
まだ試していませんが、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);
}
2 つの ArrayList をラップするオブジェクトを作成できます。両方のデータを同時に追加、削除、および変更するように、何でも記述します。