LinkedHashMapの時間計算量がHashMapの複雑さと同じである場合、なぜHashMapが必要なのですか? JavaのHashMapと比較した場合、LinkedHashMapの余分なオーバーヘッドはどれくらいですか?
LinkedHashMapはより多くのメモリを消費します。通常のHashMap
の各エントリには、キーと値があります。各LinkedHashMap
エントリには、次および前のエントリへの参照および参照があります。通常は関係ありませんが、やるべきハウスキーピングももう少しあります。
LinkedHashMapの時間計算量がHashMapの複雑さと同じである場合、なぜHashMapが必要なのですか?
複雑さとパフォーマンスを混同しないでください。 2つのアルゴリズムは同じ複雑さを持つことができますが、一方は他方よりも一貫して優れたパフォーマンスを発揮できます。
f(N) is O(N)
は次のことを意味することに注意してください。
C1*N <= limit(f(N), N -> infinity) <= C2*N
どこ C1
およびC2
は厳密に正の定数です。複雑さは、C
値がどれほど小さいか大きいかについては何も言いません。 2つの異なるアルゴリズムの場合、定数はほとんどの場合differentになります。
(そして、big-Oの複雑さは、N
が非常に大きくなるときの動作/パフォーマンスに関するものであることを忘れないでください。小さなN
値の動作/パフォーマンスについては何もわかりません。)
そうは言っても、同等のユースケースでのHashMap
操作とLinkedHashMap
操作のパフォーマンスの違いは比較的小さいです。多くの場合、より関連性の高い追加のメモリオーバーヘッド。
LinkedHashMapは、マップへのキーの挿入順序を知る必要がある場合に役立つデータ構造です。適切な使用例の1つは、LRUキャッシュの実装です。 LinkedHashMapの順序が維持されるため、データ構造にはHashMapと比較して追加のメモリが必要です。挿入順序が必須ではない場合は、常にHashMapを使用する必要があります。
HashMapとLinkedHashMapの間にはもう1つの大きな違いがあります:LinkedHashMapの場合、反復はより効率的です。
LinkedHashMapの要素は相互に接続されているため、反復には、容量に関係なく、マップのサイズに比例した時間が必要です。ただし、HashMap;の場合決まった順序がないため、反復には容量に比例した時間が必要です。
blog に詳細を記載しました。
HashMap
は挿入順序を維持しないため、二重リンクリストを維持しません。
LinkedHashMap
の最も顕著な特徴は、キーと値のペアの挿入順序を維持することです。 LinkedHashMap
は、そのために二重リンクリストを使用します。
LinkedHashMap
のエントリは次のようになります。
static class Entry<K, V> {
K key;
V value;
Entry<K,V> next;
Entry<K,V> before, after; //For maintaining insertion order
public Entry(K key, V value, Entry<K,V> next){
this.key = key;
this.value = value;
this.next = next;
}
}
Beforeとafterを使用することにより、LinkedHashMap
に新しく追加されたエントリを追跡します。これは、挿入順序を維持するのに役立ちます。
前のエントリを参照する前と後はLinkedHashMap
の次のエントリを参照します。
図とステップバイステップの説明については、 http://www.javamadesoeasy.com/2015/02/linkedhashmap-custom-implementation.html を参照してください。
LinkedHashMapはHashMapを継承します。つまり、HashMapの既存の実装を使用して、キーと値をNode(Entry Object)に格納します。これ以外に、挿入順序を維持するために、別個の二重リンクリスト実装を格納します。キーが入力されている。
それはこのように見えます:
ヘッダーノード<--->ノード1 <--->ノード2 <--->ノード3 <---->ノード4 <--->ヘッダーノード。
したがって、余分な過負荷は、この二重にリンクされたリストでの挿入と削除を維持しています。利点は次のとおりです。反復順序は、HashMapにはない挿入順序であることが保証されています。