2017-06-21 11 views
33

私の理解では、次のコードはidentityベースの比較を行っているので、falseを印刷する必要があります。私はそれがtrueを印刷している次のコードを実行するとIdentityHashMapが不正な値を返しています

はしかし、:

public class Test1 { 
    public static void main(String[] args) { 
    IdentityHashMap m = new IdentityHashMap(); 
    m.put("A", new String("B")); 
    System.out.println(m.remove("A", new String("B"))); 
    } 
} 

は、いくつかのいずれかが、私はこの動作を理解するのに役立つことはできますか?

+6

これはhttps:// stackoverflowの複製ではありません。com/questions/3052442/what-is-the-difference-between-text-and-new-stringtext、私は再オープンしました - OPがその違いを認識していることはかなりわかります:) –

+0

@OliverCharlesworth * "それはかなりクリアですOPは違いを認識しています:) "*しかし、彼はそのdupeをacceppted; D。 (しかし私は同意する、それはその質問の欺瞞ではない) – Tom

+0

@ OliverCharlesworth--私はMODの..を盲目的に信頼している間違いをした。:D –

答えて

54

実際にはJDKのバグがありました。JDK-8178355を参照してください。 IdentityHashMapには、remove(K,V)メソッドのカスタム実装が既定の方法でMapに追加されているため、この問題の原因となっています。

+0

それを超えて。そのバグレポートのコメントが、私が答えに加えたことをどのように表現しているのか、ほとんど面白いと思います。「あなたがそういったことをすると、間違ってしまうのは非常に簡単です。」 – GhostCat

+1

@GhostCatあなたの分析は非常に徹底的です。 –

+0

:-)あなたはすでに自分の投票権を持っています.SOは複数の投票を許可していないので、他の人が親指を待つだけです。 –

29

あなた "A"、新 "B"

あなたは "A" を削除し、新しい "B" だから

、はい、あなたの仮定を置いているこののIdentityHashMapべきない削除その値と正しく見えます。

しかし、あなたはベース AbstractMapのからremove(key, value)方法を使用している - この特定のサブクラスでオーバーライドではありません!だから、

javadocは言うものの:

このクラスは、キーと値を比較する時にオブジェクトの同一性の代わりにリファレンスの同一性を使用して、ハッシュテーブルを持つMapインタフェースを実装しています。

(および値)一部は(おそらく)キー/値のペアを挿入のみ実現されます。

ので、重要な部分は、再びのjavadocから来ている:

このクラスは、汎用のMap実装ではありません!このクラスはMapインターフェイスを実装しますが、意図的にMapの一般的な規約に違反します。オブジェクトの比較時にequalsメソッドを使用する必要があります。このクラスは、参照等性セマンティクスが必要となるまれなケースでのみ使用するように設計されています。

私の(たぶん強烈な)離陸:このクラスは非常に特殊なことです。それは非常に明確で狭い目的を持っています。そしてあなたはそれが崩壊する例を見つけました。 (これは意外なことではありません。セマンティクスを「変更」しても、既存のコードを再利用することに決めた場合、この種の矛盾を起こすことはほとんど不可避です)。

はバグとして見なすことができます。もう1つの答えとして確認してください:bug

+6

これは実装上のバグです。このクラスのJavadocの記述と動作が一致しません。 –

関連する問題