新しい HashMap と新しい List を作成し、任意のキーを使用して Hashmap 内に List を配置し、後で呼び出すList.clear()
と、HashMap 内に配置したものに影響しますか?
ここでのより深い質問は次のとおりです。HashMap に何かを追加するとき、新しいオブジェクトがコピーされて配置されますか、それとも元のオブジェクトへの参照が配置されますか?
ありがとう!
新しい HashMap と新しい List を作成し、任意のキーを使用して Hashmap 内に List を配置し、後で呼び出すList.clear()
と、HashMap 内に配置したものに影響しますか?
ここでのより深い質問は次のとおりです。HashMap に何かを追加するとき、新しいオブジェクトがコピーされて配置されますか、それとも元のオブジェクトへの参照が配置されますか?
ありがとう!
ここで起こっているのは、リスト自体ではなく、ハッシュマップ内のリストへのポインターを配置していることです。
定義すると
List<SomeType> list;
リスト自体ではなく、リストへのポインターを定義しています。
あなたがするとき
map.put(somekey, list);
リストではなく、ポインターのコピーを保存しているだけです。
別の場所で、そのポインターをたどってオブジェクトの末尾を変更すると、そのポインターを保持しているユーザーは、変更された同じオブジェクトを引き続き参照します。
Java での値渡しの詳細については、http://javadude.com/articles/passbyvalue.htmを参照してください。
Java は値渡し参照です。
リストをハッシュマップに追加すると、同じリストを指すハッシュマップへの参照が追加されるだけです。したがって、リストを直接クリアすると、ハッシュマップで参照しているリストが実際にクリアされます。
HashMap に何かを追加すると、新しいオブジェクトがコピーされて配置されますか、それとも元のオブジェクトへの参照が配置されますか?
これは常にオブジェクトへの参照です。HashMap をクリアしても、オブジェクトは「ライブ」のままです。その後、誰もオブジェクトを参照しなくなった場合、オブジェクトはガベージ コレクターによって破棄されます。コピーする必要がある場合は、Object.clone() メソッドと Cloneable インターフェイスを参照してください。
Map<Integer, Integer> hasmapA = new HashMap<>();
hasmapA.put("key1", "value1");
hasmapA.put("key2", "value2");
hasmapA.put("key3", "value3");
参照によるコピー: 1 つのHashMapを別の HashMap に割り当てると、両方がメモリ内の同じ参照を指します。
マップ hasmapB;
hashmapB = hashmapA;
これらのいずれかを変更すると、両方が同じ場所を参照しているため、両方のHashMapに変更が反映されます。
クローン/ディープコピー/別のメモリ ロケーションの作成/別のオブジェクトの作成
hashmapA のコンテンツをコピーする際の hashmapB の
Map<Integer, Integer> hashmapB = new HashMap<>();;
hashmapB.putAll(hashmapA)
注: ** hashmapB 宣言の両方の点の違いに気付きましたか? 2 番目のポイントでは、**HashMapコンストラクターを呼び出す必要があります。これで、hashmapA のすべてのデータを hashmapB に入れることができます。
これに対する正しい答えは次のとおりです。hashmap という HashMap があり、最初にこの HashMap にキーと値のペアを入れたとします。例: hashmap<"test1","test2">。この後、このハッシュマップを関数に渡し、その値を再び hashmap.put("test1", "test3") のように test3 に変更し、メイン メソッドでマップを再度出力すると、値による Java パスの概念はここで失敗します。
理由: HashMap を使用すると、Key(test1) のハッシュが行われ、値が格納されます。それを関数に渡して値を再度変更すると、同じキーのハッシュが再度実行され、同じメモリアドレスが取得され、それに応じて値が変更されます。そのため、キー「test1」を取得しようとすると、結果が「test3」になります。
通常、Java では常に参照を扱います ("new" [1] を使用して自分で新しいオブジェクトを明示的に作成しない限り)。
したがって、これは参照であり、マップに保存した完全なオブジェクトのコピーではありません。リストを変更すると、マップを通過するときに表示される内容にも影響します。
これは機能であり、バグではありません:)
[1] ピューリタンには「clone()」とシリアライゼーションが含まれますが、ほとんどの Java コードでは「new」がオブジェクトを取得する方法です。
やってみて
パッケージ test32; import java.util.ArrayList; java.util.HashMap をインポートします。 java.util.List をインポートします。 クラス Foo { public Foo(int id, String name) { this.id=id; this.name=name; } public static void main(String[] args) { HashMap strs = new HashMap(); // オブジェクトのリストを作成します リスト ls = 新しい ArrayList(); ls.add(新しい Foo(1, "Stavros")); ls.add(new Foo(2, "Makis")); ls.add(新しい Foo(3, "テオ")); ls.add(新しい Foo(4, "ジム")); // オブジェクトの参照をリストからハッシュマップにコピーします 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"); // 別の値を設定 f.setId(5); // 違いがリストとハッシュマップにも反映されていることを確認します System.out.println("変更後のリスト:"+ls); System.out.println("変更後のマップ:"+strs); } プライベート int id; public void setId(int id) { this.id=id; } public int getId() { this.id を返します。 } プライベート文字列名; public void setName(文字列名) { this.name=name; } public String getName() { this.name を返します。 } パブリック文字列 toString() { StringBuilder sb = new StringBuilder(); sb.append(id); sb.append("-"); sb.append(名前); sb.toString(); を返します。 } }
ねえ、みんな... Javaのすべては値渡しです。オブジェクトを渡す場合、渡す値はオブジェクト参照です。具体的には、オブジェクト参照のコピーを渡しています。Java にもポインタはありませんが、参照は似ています。正しく理解する!