プログラマーの開発メモ

ソフトウェアエンジニアの覚え書き

【Java】List、Mapのコピー(シャドウコピーとディープコピー)

2006年06月13日 18時07分37秒 | Java

List、Map等のコピーは、シャドウコピーと、ディープコピーの違いに注意する事。
シャドウコピーはインスタンスは生成されるが、元の値を参照しているだけ。

【例】クラス変数_allListの値を取り出して、その一部の内容を書き換える

package test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

public class testDate {

    protected static ArrayList _allList = null;

    public static void main(String[] args){

        // 上書き用HashMap
        HashMap mapA_2 = new HashMap();
        mapA_2.put("Aitem1", "A1-2");
        mapA_2.put("Aitem2", "A2-2");
        mapA_2.put("Aitem3", "A3-2");

        // 保存するHashMap
        HashMap mapA_1 = new HashMap();
        mapA_1.put("Aitem1", "A1");
        mapA_1.put("Aitem2", "A2");
        mapA_1.put("Aitem3", "A3");
        mapA_1.put("Aitem4", "A4");
        mapA_1.put("Aitem5", "A5");

        // listにmapA_1をセット
        ArrayList list = new ArrayList();
        list.add(mapA_1);

        // _allListに保存
        _allList = list;

        /**
         * ディープコピーの場合
         *   ⇒_allListの内容は変わらない
         */

        System.out.println("-------------------------ディープコピーの場合-------------------------");
        System.out.println("_allList:"+_allList);


        /* ディープコピーを行う */
        HashMap mapCopy1 = new HashMap();
        for(int i = 0; i <_allList.size(); i++) {                     // _allListのサイズ分ループし
            HashMap tmpMap = (HashMap)_allList.get(i);          // list内のHashMapを取得
            Set keySet = tmpMap.keySet();                       // HashMapのkeyを全て取り出し

            Iterator iteKey = keySet.iterator();                // key分イテレータで回す
            while(iteKey.hasNext()){
                String key = String.valueOf(iteKey.next());     // Keyを取得
                mapCopy1.put(key, tmpMap.get(key));             // KeyでtmpMapから値を取り出し、
            }                                                   // mapCopyに同じKeyでセットする
        }

        mapCopy1.putAll(mapA_2);                                // mapCopy1の中身をmapA_2で上書き

        ArrayList lstCopy1 = new ArrayList();                   // 新しいArrayListにADD
        lstCopy1.add(mapCopy1);

        System.out.println("lstCopy1:"+lstCopy1);
        System.out.println("_allList:"+_allList);

        System.out.println("");

        /**
         * シャドウコピーの場合
         *   ⇒_allListの内容も上書いた値で変更される
         */
        System.out.println("-------------------------シャドウコピーの場合-------------------------");
        System.out.println("_allList:"+_allList);

        ArrayList lstCopy2 = new ArrayList();
        for(int j = 0; j <_allList.size(); j++) {             // _allListのサイズ分ループし
            HashMap mapCopy2 = (HashMap)_allList.get(j);        // list内のHashMapを取得
            mapCopy2.putAll(mapA_2);                            // mapCopy1の中身をmapA_2で上書き
            lstCopy2.add(mapCopy2);                             // 新しいArrayListにADD
        }

        System.out.println("lstCopy2:"+lstCopy2);
        System.out.println("_allList:"+_allList);
    }
}


【実行結果】
-------------------------ディープコピーの場合-------------------------
_allList:[{Aitem4=A4, Aitem3=A3, Aitem2=A2, Aitem1=A1, Aitem5=A5}]
lstCopy1:[{Aitem4=A4, Aitem3=A3-2, Aitem2=A2-2, Aitem1=A1-2, Aitem5=A5}]
_allList:[{Aitem4=A4, Aitem3=A3, Aitem2=A2, Aitem1=A1, Aitem5=A5}]

-------------------------シャドウコピーの場合-------------------------
_allList:[{Aitem4=A4, Aitem3=A3, Aitem2=A2, Aitem1=A1, Aitem5=A5}]
lstCopy2:[{Aitem4=A4, Aitem3=A3-2, Aitem2=A2-2, Aitem1=A1-2, Aitem5=A5}]
_allList:[{Aitem4=A4, Aitem3=A3-2, Aitem2=A2-2, Aitem1=A1-2, Aitem5=A5}]