web-dev-qa-db-ja.com

HashMapに配置された後に値を変更すると、HashMapの内部が変更されますか?

新しいHashMapと新しいListを作成し、任意のキーを使用してHashmap内にListを配置し、後でList.clear()を呼び出すと、HashMap内に配置したものに影響しますか?

ここでより深い質問は、HashMapに何かを追加すると、新しいオブジェクトがコピーされて配置されるのか、元のオブジェクトへの参照が配置されるのかということです。

ありがとう!

33
Diego

ここで起こっているのは、リスト自体ではなく、ハッシュマップ内のリストにpointerを配置していることです。

定義するとき

List<SomeType> list;

リスト自体ではなく、リストへのポインタを定義しています。

するとき

map.put(somekey, list);

リストではなく、pointerのコピーを保存するだけです。

他のどこかで、そのポインタをたどってそのオブジェクトを最後に変更した場合、そのポインタを保持している人はまだ同じ変更されたオブジェクトを参照しています。

Javaでの値渡しの詳細については、 http://javadude.com/articles/passbyvalue.htm をご覧ください。

45

Javaは値による参照渡しです。

リストをハッシュマップに追加すると、同じリストを指すハッシュマップへの参照が追加されるだけです。したがって、リストを直接クリアすると、ハッシュマップで参照しているリストが実際にクリアされます。

12
James Camfield

HashMapに何かを追加すると、新しいオブジェクトがコピーされて配置されますか、それとも元のオブジェクトへの参照が配置されますか?

常にオブジェクトへの参照です。 HashMapをクリアすると、オブジェクトは「ライブ」のままになります。誰もそれを参照していない場合、オブジェクトはガベージコレクターによって破棄されます。コピーする必要がある場合は、Object.clone()メソッドとCloneableインターフェイスを見てください。

4
daitangio
Map<Integer, Integer> hasmapA = new HashMap<>();
hasmapA.put("key1", "value1");
hasmapA.put("key2", "value2");
hasmapA.put("key3", "value3");
  1. 参照によるコピー:一方HashMapを他方に割り当てる場合、両方のポイントメモリ内の同じ参照へ。

    マップhasmapB;

    hashmapB = hashmapA;

これらのいずれかを変更すると、両方が同じ場所を参照しているため、変更は両方HashMapに反映されます。

  1. 値でコピー:

クローン/ディープコピー/個別のメモリロケーションの作成/個別のオブジェクトの作成

hashmapAのコンテンツをコピー中のhashmapBの

Map<Integer, Integer> hashmapB = new HashMap<>();;

hashmapB.putAll(hashmapA)

注:** hashmapB宣言の両方の点に違いがあることに気づきましたか? 2番目のポイントでは、** HashMapコンストラクターを呼び出す必要があります。 hashmapAのデータをhashmapBにputAllできるようにするためです。

参照

2

これに対する正解は以下に説明されています:hashmapというHashMapがあり、最初にこのHashMapにキーと値のペアを配置するとします。 hashmap <"test1"、 "test2">。この後、このハッシュマップを関数に渡し、hashmap.put( "test1"、 "test3")のように値を再びtest3に変更し、メインメソッドでJava =値概念によるパスはここで失敗します。

理由は次のとおりです。HashMapを使用すると、Key(test1)のハッシュが実行され、値が保存されます。関数に渡して値を再度変更すると、同じキーのハッシュが再度実行され、同じメモリアドレスが取得され、それに応じて値が変更されます。そのため、キー「test1」を取得しようとすると、結果が「test3」として返されます。

1

やってみよう

 package test32; 
 
 import Java.util.ArrayList; 
 import Java.util.HashMap; 
 import Java.util.List; 
 
 class Foo {
 public Foo(int id、String name){
 this.id = id; 
 this.name = name; 
} 
 
 public static void main(String [] args){
 HashMap strs = new HashMap(); 
 
//オブジェクトのリストを作成
 List ls = new ArrayList(); 
 ls.add(new Foo(1、 "Stavros")); 
 ls.add(new Foo (2、 "Makis")); 
 ls.add(new Foo(3、 "Teo")); 
 ls.add(new Foo(4、 "Jim")); 
 
 //リストのオブジェクトの参照をハッシュマップにコピーします
 strs.put( "1"、ls.get(0)); 
 strs.put( " 2 "、ls.get(1)); 
 strs.put(" 3 "、ls.get(2)); 
 strs.put(" 4 "、ls.get(3 )); 
 
 System.out.println( "変更前のリスト:" + ls); 
 System.out.println( "変更前のマップ:" + strs); 
 //ハッシュマップからオブジェクトを取得
 Foo f = strs.get( "1"); 
 // diを設定fferent value 
 f.setId(5); 
 //リストおよびハッシュマップにも差異が反映されることを確認します
 System.out.println( "変更後のリスト: "+ ls); 
 System.out.println("変更後のマップ: "+ strs); 
} 
 
 private int id; 
 public void setId(int id){
 this.id = id; 
} 
 public int getId(){
 return this.id; 
} 
 
 private String name; 
 public void setName(String name){
 this.name = name; 
} 
 public String getName(){
 return this.name; 
} 
 
 public String toString(){
 StringBuilder sb = new StringBuilder(); 
 sb.append(id); 
 sb.append( "-"); 
 sb.append(name); 
 return sb。 toString(); 
} 
} 
1
stavros

通常、常にJavaで参照を処理します(「new」[1]を使用して自分で明示的に新しいオブジェクトを作成しない限り)。

したがって、これは参照であり、マップに保存したオブジェクトの完全なコピーではありません。また、リストを変更すると、マップを表示するときに表示される内容に影響します。

これは機能であり、バグではありません:)

[1] Puritansには「clone()」とシリアル化が含まれますが、ほとんどの場合Java code "new"はオブジェクトを取得する方法です。