2012-04-11 2 views
1

0から7まで番号が付けられた8つのバケットしかないLinkedHashMapオブジェクトがあるとします。 今、要素を追加します。私は7つの要素を追加し、結果は次のようになります。衝突の際にLinkedHashMapから要素を取得する時間の複雑さは何ですか?

1)Element_1:バケット番号2これは、LinkedHashMapが挿入順序を維持するために維持するリンクリストの開始となります。
1)Element_2:これはElement_1
2に連結されたバケット番号3)Element_3:バケット番号1これはElement_2
3に連結されている)Element_4:バケット番号4は、これはElemetn_3
4に連結されている)Element_5バケット番号5:これはElement_4にリンクされています
5)Element_6:バケット番号3これはElement_5(衝突が発生しました)にリンクされています
6)Element_7:バケット番号3これはElement_6(再び衝突)

ここで、Element_7を取得したいとします。この要素のハッシングにより、私はバケット番号3となります。今バケット番号3の要素は、Element_2Element_6Element_7です。
したがって、次の2つのトラバーサルの順番はどのくらいですか:
a)Element_2-> Element_3-> Element_4-> Element_5-> Element_6-> Element_7です。
または
b)Element_2-> Element_6-> Element_7。

私は、(a)LinkedHashMapはリンクオーダーを維持するためのリンクリストを保持しているので、その答えはと考えました。したがって、順序が(b)の場合は、特定の要素が2つの参照を格納していることを意味します。挿入順序の次の要素と、同じバケット内の次の要素の要素です。

答えが(b)の場合、特定の要素がどのように判断するのですか。 2つの参照のうち、どちらを選択するかを指定します。

ユースケースシナリオは仮想的なものであり、バケット数よりも少ない要素数では衝突の可能性が低いという事実とは相関していない可能性があります。 上記のシナリオに留意して回答してください。
ありがとうございます。

+0

挿入順リンクリストは、キーでアイテムを検索するコストとはまったく関係がないようですか?言い換えれば、検索のコストは 'HashMap'のものと同じでなければなりません。 – NPE

+1

結果がa)の場合は非常に奇妙です(そしてかなり無意味です)。それはリンクされたリストに過ぎません! – dlev

+0

7つの要素がある場合、通常は16個のバケットがあります。しかし、この例はまだ有効です。 –

答えて

1

LinkedHashMapはHashMapを拡張しているため、リンクはgetとは関係がありません。リンクを追加すると、LinkedHashMapの効率が低下することはありません。get - getにはそのリンクは必要ありません。

+0

私は結論に同意しますが、推論の連鎖が完全に説得力があるとは言えません。 – NPE

+0

@aix、あなたは正しいです。追加された "、そう..."。 –

+0

はい、確かに私はこの実装に気付きました。しかし、私が言ったように、通常のHashMapでは、特定のエントリ(Map.Entryオブジェクト)は(同じバケット内の)次のMap.Entryオブジェクトの参照を格納しますが、LinkedHashMapの場合、参照は次に挿入された要素になります。したがって、同じバケット内の要素を反復処理するには、特定の要素に2つの参照が格納されます(1つは次の挿入要素用、もう1つは同じバケット内にあります)。はいの場合、どのように決定するのですか、どの参照を選択するのですか? –

1

LinkedHashMapはHashMapを拡張し、そのgetメソッドはHashMapのgetEntryメソッドを呼び出します。 HashMapの実装では、各バケットは別々の配列に格納されるため、データセット全体をループする必要はなく、そのバケット内のデータのみをループします。採取フォームオラクルJDK 7:

final Entry<K,V> getEntry(Object key) { 
    int hash = (key == null) ? 0 : hash(key.hashCode()); 
    for (Entry<K,V> e = table[indexFor(hash, table.length)]; 
     e != null; 
     e = e.next) { 
     Object k; 
     if (e.hash == hash && 
      ((k = e.key) == key || (key != null && key.equals(k)))) 
      return e; 
    } 
    return null; 
} 

EDIT

e.nextHashMap.Entryで定義され、e.afterと異なるバケットにすることができるLinkedHasMap.Entryで定義さe.beforeとは対照的に、同じバケット内にあります。

+0

はい、実際にこの実装に気付きました。しかし、私が言ったように、通常のHashMapでは、特定のエントリ(Map.Entryオブジェクト)は(同じバケット内の)次のMap.Entryオブジェクトの参照を格納します しかし、LinkedHashMapの場合、参照は次に挿入された要素になります。したがって、同じバケット内の要素を反復処理するには、特定の要素に2つの参照が格納されます(1つは次の挿入要素用、もう1つは同じバケット内にあります)。 「はい」の場合、選択方法はどのように決まりますか? –

+0

私の編集を参照してください: 'LinkedHashMap.Entry'は' HashMap.Entry'を拡張し、マップの次のノードと前のノードである(前とは異なるバケットにある可能性がある) 'before'フィールドと'after'フィールドを追加します。 'get'を呼び出すと、同じバケット内にある' Map.Entry'の 'next'フィールドが使用されます。 – assylias

+0

こんにちはアシリアス、私はあなたが間違いなく正しいと思うのは、マップだけが意味があるからです。しかし、相互説明のために、2つの参照があります。フィールド "after"は挿入順序参照を格納し、 "next"は同じバケット内の次の要素への参照を格納します。 何度も何度も何度も何度も聞いて申し訳なく思っていますが、私は混乱してしまいました。 –

関連する問題