JavaのCollectionをコピーしてハマったので整理し直す

2017/09/04

とあるアプリを作っていてハマったので頭の整理を兼ねて。 やりたかったのは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




関連(するかもしれない)記事


おススメ