web-dev-qa-db-ja.com

HashMapのtoString関数が異なる順序で自分自身を出力するのはなぜですか?

私はこの非常に単純なコードを使用しており、Map内のさまざまな種類のオブジェクトを少し遊んでみました。

//There's a bit of spanish, sorry about that
//just think 'persona1' as an object with
//a string and an int
Map mapa = new HashMap();
mapa.put('c', 12850);
mapa.put(38.6, 386540);
mapa.put("Andrés", 238761);
mapa.put(14, "Valor de 14");
mapa.put("p1", persona1);
mapa.put("Andrea", 34500);

System.out.println(mapa.toString());

そして、私はコンソールから次のようなものを期待しています:

{c=12850, 38.6=386540, Andrés=238761, 14=Valor de 14, p1={nombre: Andres Perea, edad: 10}, Andrea=34500}

しかし、驚いたことに、同じデータを別の順序で取得しました。

{38.6=386540, Andrés=238761, c=12850, p1={nombre: Andres Perea, edad: 10}, Andrea=34500, 14=Valor de 14}

他の種類のオブジェクトを試しても、文字列や数値タイプだけを試してもかまいません。常に同じように動作し、見た目はまったく意味のない別の順序になります。

なぜこれが起こるのか誰かが私にヒントを与えることができますか?それとも、私が見逃している明らかなものかもしれませんか?

Java 1.7とEclipse Junoを使用しています。

11
unmultimedio

Oracleのドキュメントに従って

HashMapクラスは、非同期でnullを許可することを除いて、Hashtableとほぼ同じです。このクラスは、マップの順序を保証しません。特に、順序が長期にわたって一定であることを保証するものではありません。

HashMap JavaDocsを参照してください。

20
Vimal Bera

Javaでマップインターフェイスを実装する3つのクラスがあります。 1. hashMap:Idは順序を保証しません。 2.リンクされたHashMap:挿入順に格納します。 3. TreeMap:昇順で格納されます。(ASCII値)

だからあなたの要件に従って、あなたは書く代わりにHashMap.soの代わりにリンクされたHashMapを使うことができます

Map mapa = new HashMap();

リンクされたHashMapのオブジェクトを作成する

Map mapa = new LinkedHashMap();

詳細については、以下のリンクに従ってください。

http://docs.Oracle.com/javase/tutorial/collections/interfaces/map.html

16
TheGraduateGuy

HashMap 要素の順序は保証されません。順序を維持したい場合は、 LinkedHashMap を使用します。

次のケースを見る

    Map<Integer,String> unOrderedMap=new HashMap<>();
    unOrderedMap.put(1,"a");
    unOrderedMap.put(3,"a");
    unOrderedMap.put(2,"a");
    System.out.println("HashMap output: "+unOrderedMap.toString());

    Map<Integer,String> orderedMap=new LinkedHashMap<>();
    orderedMap.put(1,"a");
    orderedMap.put(3,"a");
    orderedMap.put(2,"a");
    System.out.println("LinkedHashMap output: "+orderedMap.toString());

出力:

   HashMap output: {1=a, 2=a, 3=a}
   LinkedHashMap output: {1=a, 3=a, 2=a}

マップは要素が追加された順序を維持しません。リストは要素の順序を維持します

「マップの順序は、マップのコレクションビューのイテレータが要素を返す順序として定義されます。TreeMapクラスなどの一部のマップ実装は、その順序に関して特定の保証を行います。HashMapクラスなどの他の実装は、 」

1
upog

これがハッシュマップの仕組みです:(別のソースからの引用)


キーと値のペアを格納するために使用する「バケット」の数があります。各バケットには一意の番号があり、それがバケットを識別します。キーと値のペアをマップに入れると、ハッシュマップはキーのハッシュコードを調べ、そのペアを、識別子がキーのハッシュコードであるバケットに格納します。例:キーのハッシュコードは235です->ペアはバケット番号235に保存されます(1つのバケットが複数のキーと値のペアを保存できることに注意してください)。

ハッシュマップでキーを指定して値を検索すると、最初に、指定したキーのハッシュコードが確認されます。ハッシュマップは対応するバケットを調べ、equals()と比較して、指定したキーとバケット内のすべてのペアのキーを比較します。

これで、これがマップでキーと値のペアを検索するのに非常に効率的であることがわかります。キーのハッシュコードによって、ハッシュマップはどのバケットを参照するかをすぐに認識できるため、そのバケットの内容に対してテストするだけで済みます。

上記のメカニズムを見ると、キーのhashCode()およびequals()メソッドに必要な要件もわかります。

  • 2つのキーが同じである場合(equals()が比較するとtrueを返す)、それらのhashCode()メソッドは同じ数を返す必要があります。キーがこれに違反する場合、等しいキーは異なるバケットに格納される可能性があり、ハッシュマップはキーと値のペアを見つけることができません(同じバケットを検索するため)。

  • 2つのキーが異なる場合、それらのハッシュコードが同じかどうかは関係ありません。ハッシュコードが同じ場合、それらは同じバケットに格納されます。この場合、ハッシュマップはequals()を使用して区別します。


これで、すべての「キーと値」のペアをハッシュマップに入れて印刷すると、値をハッシュすることによって生成されたキーのランダムな順序でそれらが印刷されますyouキーに提供されます。

順序付けを維持するための要件が​​stillである場合は、JavaでLinkedHashMapを使用できます。

お役に立てれば :-)

編集:元の投稿: Java HashMapは同じハッシュコードで異なるオブジェクトをどのように処理しますか?

0
VictorCreator