- PR -

コレクションクラスに関して

投稿者投稿内容
カメ吉
会議室デビュー日: 2006/04/03
投稿数: 7
投稿日時: 2006-04-10 16:23
お世話になってます。カメ吉です。

コレクションクラスに関してご質問があります。

コレクションクラスを使用して値をセットする処理を
以下のようのコーディングしました。

コード:

/**
* メインクラス
*
* HashMapに値を追加、更新し
* setter・getterのクラスのitemListに追加する
*/
public class Test013 {
public static void main(String[] args) {
System.out.println("スタート");

// インスタンス化
ListClass listClass = new ListClass();

ArrayList beforList = new ArrayList();

// @ArrayListにHashMapを追加
HashMap itemMap = new HashMap();
itemMap.put("1","1");
beforList.add(itemMap);
listClass.setItemList(beforList);

// AArrayListを取得しHashMapの値を変更
ArrayList afterList = listClass.getItemList();
Iterator iterAft = afterList.iterator();
while (iterAft.hasNext()) {
HashMap hensyuMap = (HashMap) iterAft.next();
String str = (String)hensyuMap.get("1");
System.out.println("変更前【" +str +"】");
str = str +"2345";
hensyuMap.put("1",str);
}

// B再度ArrayListを取得しHashMapの値を確認
Iterator itemIter = listClass.getItemList().iterator();
while (itemIter.hasNext()) {
HashMap kakuninMap = (HashMap) itemIter.next();
System.out.println("変更後【" +kakuninMap.get("1") +"】");
}
System.out.println("エンド");
}
}

/**
* メインクラス
*
* itemListのsetter・getterクラス
*/
public class ListClass {
private ArrayList itemList;
/**
* @return itemList を戻します。
*/
public ArrayList getItemList() {
return itemList;
}
/**
* @param itemList itemList を設定。
*/
public void setItemList(ArrayList itemList) {
this.itemList = itemList;
}
}



@の箇所で、itemListにHashMapを追加しました。
Aの箇所で、itemListを取得しHashMapの値を変更しました。
Bの箇所で、再度itemListを取得しHashMapの値を確認
しています。

質問の内容は以下の通りです。
なぜ、itemList自体には何も変更していないにも関わらず、
Bの箇所で値を確認するとHashMapの内容が変更されて
いるかが良く分かりません。

iteratorを使用すると、setter・getterクラスのitemListを
そのまま変更してしまうのでしょうか?

すみませんが、ご教授の程、宜しくお願い致します。

#プログラムのコードに[CODE]を付与しました。

[ メッセージ編集済み 編集者: カメ吉 編集日時 2006-04-13 11:25 ]
想馬
大ベテラン
会議室デビュー日: 2003/05/29
投稿数: 245
お住まい・勤務地: 神奈川・東京
投稿日時: 2006-04-10 16:43
オブジェクトは参照渡しですよ。(参照の値渡しって感じなのかな・・・)

# 括弧の部分を追加

[ メッセージ編集済み 編集者: 想馬 編集日時 2006-04-10 16:49 ]
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2006-04-10 16:51
なぜかといえば、(1)で追加したHashMapオブジェクトと(2)で取得したHashMapオブジェクトと
(3)で取得したHashMapオブジェクトが同じものだからです。Collectionオブジェクトは他の
オブジェクトへの参照を格納するだけであり、Collectionオブジェクトから見れば、(2)と(3)
では(1)で追加されたオブジェクトへの参照を受け渡しているだけです。
カメ吉
会議室デビュー日: 2006/04/03
投稿数: 7
投稿日時: 2006-04-10 17:11
想馬さん、ukさん、回答ありがとうございます。

A、Bの処理で行っているのは、
参照(itemList)をコピー((HashMap) iterAft.next())して、
コピー先(afterList)で参照先を変更(hensyuMap.put("1",str))している。
その為、コピー元(itemList)にも影響(変更されている)がある
ということで合っていますでしょうか?

ご指摘の程、宜しくお願い致します。
想馬
大ベテラン
会議室デビュー日: 2003/05/29
投稿数: 245
お住まい・勤務地: 神奈川・東京
投稿日時: 2006-04-10 17:21
あってます。

オブジェクトは参照(値)渡しなので、getItemList()で取得したオブジェクトはListClassクラスのフィールドに定義されているitemListと同じオブジェクトです。
つまりgetItemList()で取得したリストの中身を変更すれば同じアドレスを参照しているitemListの中身も変更されます。

取り出したオブジェクトに変更を加えるけど元のオブジェクトに影響を与えたくないという場合は、cloneメソッドで複製した方に変更を加えれば元のオブジェクトには影響がありません。

# ちょっと追加

[ メッセージ編集済み 編集者: 想馬 編集日時 2006-04-10 17:26 ]
カメ吉
会議室デビュー日: 2006/04/03
投稿数: 7
投稿日時: 2006-04-10 17:29
想馬さん、回答ありがとうございます。

例えば、元のArrayList情報を残して、
編集したArrayList情報の両方が必要となった場合、
ListClassクラスに、
編集前のArrayListと
編集後のArrayListの2つの変数を用意すれば良いのでしょうか?

ご指摘の程、宜しくお願い致します。
想馬
大ベテラン
会議室デビュー日: 2003/05/29
投稿数: 245
お住まい・勤務地: 神奈川・東京
投稿日時: 2006-04-10 17:35
ListClassクラスがそういう設計(例えばbeforeListとafterListを持つクラス)であればそれでいいと思います。
編集前、編集後の2つの情報を両方持つのであれば1つのListClassクラスに2つフィールドを持つか、ListClassを2つインスタンス化して1つは編集前、もう1つは編集後を持つように管理しないと無理だと思います。

# 定時なので帰ります・・・
カメ吉
会議室デビュー日: 2006/04/03
投稿数: 7
投稿日時: 2006-04-11 10:44
想馬さん、回答ありがとうございます。

ひとつ、疑問に思ったことがあります。

// A-1
ArrayList newList = new ArrayList();

Iterator iterAft = afterList.iterator();
while (iterAft.hasNext()) {
HashMap hensyuMap = (HashMap) iterAft.next();
String str = (String)hensyuMap.get("1");
System.out.println("変更前【" +str +"】");
str = str +"2345";
hensyuMap.put("1",str);

// A-2.以下のようにListClassクラスに再セットする処理は不要ですか?
newList.add(hensyuMap);
listClass.setItemList(newList);
}

参照の(値)渡しのため、参照先を(直接?間接?)変更しているので
再度、変更したMapをListClassクラスのitemListへ再セットする
必要はないのでしょうか?

すみませんが、ご指導の程、宜しくお願い致します。

スキルアップ/キャリアアップ(JOB@IT)