JavaのCollectionをコピーしてハマったので整理し直す
とあるアプリを作っていてハマったので頭の整理を兼ねて。 やりたかったのはArrayListのコピーだったんですが、Deep Copyになっていると思い込んでいた箇所が実はShallow Copyになっていて変なバグが出ていました。そりゃダメだ。
そもそもDeep CopyとShallow Copyって何?というあたりはシャローコピーとディープコピーの違い - くろの雑記帳が分かりやすいですね。Deep Copyは参照のコピー、Shallow Copyは実体のコピーです。
で、実装の話になると
- 例えばArrayListの場合、中身がプリミティブならnew ArrayList(list)でDeep copyになる
- プリミティブじゃないなら自前でDeep copyする必要がある
- Deep copyのためにオブジェクトを複製する場合、cloneメソッドを実装するかコピーコンストラクタを用意するのがセオリー
という感じになるようです。
簡単なコード例をまとめておきます。 中身がプリミティブの場合。
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
List<String> copied = new ArrayList(list);
cloneメソッドを実装した場合。
List<Item> list = new ArrayList<>();
list.add(new Item(...));
list.add(new Item(...));
list.add(new Item(...));
List<Item> copied = new ArrayList<>();
for(Item item : list) {
copied.add((Item) item.clone());
}
コピーコンストラクタを実装した場合。
List<Item> list = new ArrayList<>();
list.add(new Item(...));
list.add(new Item(...));
list.add(new Item(...));
List<Item> copied = new ArrayList<>();
for(Item item : list) {
copied.add(new Item(item));
}
今回はコピーコンストラクタを使って複製することにしました。cloneはなんかしっくりこないんですよね...
参考URL
関連(するかもしれない)記事
おススメ