2

いくつかの要素を繰り返しHashMapて他のマップに書き直そうとしていますが、次の問題があります。

@Test
public void test() {
    Map<SubClass, String> map = new HashMap<SubClass,String>();
    Map<SubClass, String> anotherMap = new HashMap<SubClass,String>();
    map.put(new SubClass(), "10");

    for(SubClass i : map.keySet()) {
        System.out.println(i); // initial (because toString is implemented)
        System.out.println(map.get(i)); // 10
        // here it's ok...

        i.name="another";

        System.out.println(i); // another
        System.out.println(map.get(i)); // null!
        // but here it occurs that  map.get(i) returns null!

        anotherMap.put(i, map.get(i));
    }
    for(SubClass i : anotherMap.keySet()) {
        System.out.println(i); // another
        System.out.println(map.get(i)); // null!
    }
}
// SubClass has String name; and hashCode and equals implemented

javadocによると:

java.util.Map.keySet()

このマップに含まれるキーの Set ビューを返します。セットはマップに支えられているため、マップへの変更はセットに反映され、その逆も同様です。セットに対する反復の進行中にマップが変更された場合 (反復子自体の削除操作を除く)、反復の結果は未定義です。セットは、Iterator.remove、Set.remove、removeAll、retainAll、および clear 操作を介して、マップから対応するマッピングを削除する要素の削除をサポートします。add または addAll 操作はサポートされていません。

「マップへの変更はセットに反映され、その逆も同様です」と書かれています。では、なぜこのように動作し、最も重要なのか: 両方のマップに変更されたキーと null 以外の値のみが含まれるようにするにはどうすればよいでしょうか?

更新: 私の友人は Java 1.5.0.19 (私は 1.7.0_03 を持っていますが、1.5.0_21 でも同じことが起こります) でこのテストを行い、正しい出力を得ました:

initial
10
another
10

UPDATE2: ああ、彼は hashCode/equals を実装していないので、最初の更新は関係ありません

4

5 に答える 5

5

mapではなくkeyを変更しています。その中のオブジェクトが変更されたことを が検出する方法はありません。マップに変更を「表示」させるには、 を呼び出し、キーを変更してから、を呼び出す必要があります。Map<K,V>remove(originalKey)put(modifiedKey,object)

clearマップの変更は、 、putputAll、またはへの呼び出しになりますremove

于 2012-07-05T15:32:38.300 に答える
4

java.util.Map javadocごとに:

注: 変更可能なオブジェクトをマップ キーとして使用する場合は、細心の注意を払う必要があります。オブジェクトがマップ内のキーであるときに、等値比較に影響を与える方法でオブジェクトの値が変更された場合、マップの動作は指定されません。

つまり、マップ内でのキーのインデックス作成方法に影響を与えるような方法でキー オブジェクトを変更した場合、マップが正しく機能する必要はありません。

于 2012-07-05T18:19:41.967 に答える
0

オブジェクトi.name = "another"のハッシュコードを変更していると思います。そのため、値が返されます。の関数がを使用しない場合、コードは機能します。SubClass inullhashcodeSubclassname

だからあなたが電話するときanotherMap.put(i, map.get(i));あなたは本当に電話しているanotherMap.put(i, null);

の目的は、HashMapO(1)時間でルックアップを実行することです。そのため、からハッシュコードを取得しSubClass i、更新しません。あなたの提案は怠惰なものを必要としますHashMapが、それはO(n)の時間を要し、目的を打ち負かします。

于 2012-07-05T15:33:13.110 に答える
0

次のようなもので試してください:

for(SubClass i : map.keySet()) {
    Object old = map.get(i);

    i.name="another";

    anotherMap.put(i, old);
}
于 2012-07-05T15:33:42.520 に答える
-1

私の友人は以前にここにいる誰よりも優れた解決策を得たので、私は自分自身に答えています:

for (Map.Entry<SubClass, String> entry: map.entrySet()) {
    System.out.println(entry.getKey().name);
    System.out.println(entry.getValue());

    entry.getKey().name = "another";

    System.out.println(entry.getKey().name);
    System.out.println(entry.getValue());
}

これはうまくいきます:)

于 2012-07-05T15:44:10.583 に答える