2016-07-28 7 views
0

マップにリスト挿入を使用していて、挿入動作を理解できません。挿入時のマップとリストの値のあいまいさ:java

public class TestList { 

public static void main(String[] args) { 

    String strarray[] = new String[5]; 

    for(int i = 0; i < 5; i++){ 

     strarray[i] = "Demo" + i; 
    } 

    Map<Integer, List<String>> cluesByText = new HashMap<Integer, List<String>>(); 
    int j = 0; 
    for (String str : strarray) { 

     System.out.println(str); 
     List<String> s = cluesByText.get(str); 
     if (s == null) { 
      s = new LinkedList<String>(); 
      cluesByText.put(j, s); 
     } 

     s.add(str); 
     s.add(str); 
     s.add(str); 
     s.remove(1); 
     // why it is storing without doing cluesByText.put(j,s); 
     j++; 
    } 

    //output is: 

    System.out.println(cluesByText); 

} 
} 

問題がマップにリストの挿入を実行した後、挿入してリストの内容を変更するに/削除操作している間、それは 前の行にマップに格納されたリストに反映されてきています。

最終出力来ている地図の内容です。

{0=[Demo0, Demo0], 1=[Demo1, Demo1], 2=[Demo2, Demo2], 3=[Demo3, Demo3], 4=[Demo4, Demo4]} 

リストの状態が既にマップに格納されているため、このように起こっているのはなぜわかりませんか?

+0

挿入したリストの値は、依然として元のリストの値を指しています。 –

+1

質問には関係ありませんが、コードはあまり意味がありません。 'cluesByText.get(str)'は、マップのキーが文字列ではなく整数であるため、常にnullを返します。 – Eran

答えて

0

List<String>への参照があるので、リストに追加することができます。マップにエントリがない場合は、新しいList<String>が作成され、エントリがマップに追加されます。それにかかわらず、List<String>の範囲は、それを動作させるために利用可能にする。

1

これは予想される動作です。リストの参照はコピーではなくマップに保存しています。同じリストはsで参照されていますので、sでリストに追加すると、マップから実際に見えます。同じオブジェクトへの参照が2つだけです。

1

Javaの(ほぼ)すべてがREFERENCEであり、値ではないことに注意してください。だから、あなたが持っているのは、リストの "状態"ではなく、整数からリストの "アドレス"へのマップです。

リストに保存されている情報を習得すると、コンピュータはそのアドレスに移動してその情報を表示します。

sをそのリストに割り当てると、そのアドレスが取り込まれ、sに格納されます。

s.add()またはs.remove()でそのリストを変更すると、そのアドレスに移動します(マップにある同じアドレス)。そこに変更が加えられます。

したがって、最終的にマップからそのアドレスに戻ると、同じ値が表示されます。

s=演算子を割り当てたのは、唯一のケースです。次に、実際に別のアドレスを上書きしているため、元のアドレスを見ているものは影響を受けません。

関連する問題