LinkedHashMapコアソースコード分析

いったん人々が自分自身を認めれば、彼らはそれほど社交的ではない。
-「中級コレクション」

0序文

順序付けされていないHashMap、キーでソートされたTreeMap、つまりLinkedHashMapの特徴は何ですか?挿入の順序を維持します。LinkedHashMapもBloch(Javaコレクションフレームワーク全体を開発した人)からのものです。

  • 要素の格納関係

    赤と黄色の矢印:要素を追加する順序
    青い矢印:単一のリンクリストの各要素の格納順序
    head:リンクリストヘッド
    テール:リンクリストテール

1継承体系

  • HashMapから継承されているため、HashMapの栄光もあります。
    5088755_1577812744625_DA615EAF7757A05A68BDC4C9093BBBD8

2プロパティ

  • 二重リンクリストの先頭(最も古い)

  • 二重リンクリストの終わり(最小)

  • HashMap.Nodeのサブクラス:通常のLinkedHashMapノード、二重にリンクされたリストの構造を維持するためにbefore属性とafter属性を追加します

  • このLinkedHashMapの反復ソートメソッド:
    true:アクセス順序
    false(デフォルト):挿入順序

3工法

コンストラクターは、最初に親クラスHashMapを実行するコンストラクターです。

3.1パラメータなし

  • 挿入順序、デフォルトの初期容量(16)、負荷係数(0.75)を維持する空のLinkedHashMapインスタンスを作成します。

3.2参加

  • 空のLinkedHashMapインスタンスを作成します。初期容量、負荷係数、並べ替えモードを指定できます。
  • 挿入順序を維持するLinkedHashMapインスタンスを作成します。インスタンスには、指定されたマップと同じマッピング関係があります。作成されたLinkedHashMapインスタンスには、デフォルトの負荷係数(0.75)と、指定されたマップにマップを収容するのに十分な初期容量があります。

以下では、このクラスの主な機能がコードを通じてどのように実装されるかを調べ始めます。

4挿入順にアクセス

LinkedHashMapのデフォルトのaccessOrderはfalseで、挿入順序に従ってアクセスを提供し、親クラスHashMapのputメソッドをオーバーライドしません。ただし、HashMapでは、putはHashMapのノードノードです。LinkedHashMapのエントリはその構造とは異なり、どのように確立されますか二重にリンクされたリストはどうですか?LinkedHashMapを見て、関連するコードを挿入してみましょう。

書き換えられていないput => putValueコード部分を無視して、書き換えられたコードを直接観察します。

newNode

  • HashMap
  • LinkedHashMap書き換え

    新しいノードの制御はとても新しいノードが最後に追加されるたびにことを、あなたは挿入順序ことを確認することができ、リストの最後に追加されます。
    linkNodeLastを研究し続けます

linkNodeLast

ノードを追加し、リンクリストの最後に追加します。

1

2

4

5

6

7

8

9

10

11

12

13

14

15

// link at the end of list

private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {

    LinkedHashMap.Entry<K,V> last = tail;

    // 新增于尾节点

    tail = p;

    // last 为null,说明链表为空

    if (last == null)

        head = p;

    // 链表非空,建立新节点和上一个尾节点的前后关系

    else {

        // 将新节点 p 直接接在链尾

        p.before = last;

        last.after = p;

    }

}

ヘッドノードとテールノードを追加することにより、HashMapに基づいてノードの前後の属性を追加することで、ノードを追加するたびにノードをテールノードに直接追加でき、挿入順序に従ったメンテナンスを実現できることがわかります。リンクされたリスト構造の目的!



  • グラフのリンクリストを作成する手順青い部分はHashMapのメソッドです
    オレンジの部分はLinkedHashMapのユニークなメソッドです

LinkedHashMapも二重リンクリストですが、最初から最後まで挿入順に一方向のアクセスしか提供せず、LinkedListほどアクセスしにくいことに注意してください。

  • LinkedHashMapにはイテレータを介してアクセスします。デフォルトでは、ヘッドノードから開始します。

    反復処理中は、常に後ノードにアクセスして走査を完了します

    。1か所をチェックし
    て、属性の後のノードを介して2か所から後続ノードを見つけます

5リンクされたリストノードの削除

  • LinkedHashMap後処理を可能にするHashMapに格納されたコールバックは、

    挿入操作と同じです。LinkedHashMap削除操作に関連するコードも、親クラスによって直接実装されます。ノードを削除するときに、親クラスはLinkedHashMapの二重リンクリストを修復しません。では、ノードを削除した後、削除したノードを二重リンクリストから安全に削除するにはどうすればよいですか?実際、ノードを削除した後、コールバックメソッドafterNodeRemovalが呼び出されます。LinkedHashMapはこのメソッドを書き換えます。

1

2

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

// e 为已经删除的节点

void afterNodeRemoval(Node<K,V> e) { // unlink

    LinkedHashMap.Entry<K,V> p =

        (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;

    // 将 p 节点的前驱后后继引用置 null,辅助 GC

    p.before = p.after = null;

    // p.before 为 null,表明 p 是头节点

    if (b == null)

        head = a;

    else

        // 否则将 p 的前驱节点连接到 p 的后继节点

        b.after = a;

    // a 为 null,表明 p 是尾节点

    if (a == null)

        tail = b;

    else

        // 否则将 a 的前驱节点连接到 b

        a.before = b;

}

要素を削除する主なプロセス:

  1. ハッシュに従ってバケットを配置する
  2. リンクされたリストをトラバースするか、赤黒ツリーに関連する削除メソッドを呼び出します
  3. ノードのLinkedHashMapメンテナンスの二重リンクリストから削除する削除
    5088755_1583897219283_48356470140921DD4FA1E2C40982DE97uploading.4e448015.gifダンプが失敗した再アップロードをキャンセル

6 LRU(最近使用されていない、最も使用されていない)

3.2.1栗

アクセス頻度の高い要素はキューの最後に追加されるため、アクセス頻度の低いデータは当然チームのトップに近く、マップ要素の数が多い場合などの削除戦略を設定して、ヘッドノードを削除できます。

3.2.2要素はチームの最後に移動されました

取得すると、要素は行末に移動します。

1

2

4

5

6

7

8

9

10

11

public V get(Object key) {

    Node<K,V> e;

    // 调用 HashMap  get 方法

    if ((e = getNode(hash(key), key)) == null)

        return null;

    // 如果设置了 LRU 策略

    if (accessOrder)

    // 这个方法把当前 key 移动到队尾

        afterNodeAccess(e);

    return e.value;

}

上記のソースコードから、現在のアクセスノードが、単なるgetメソッドではなく、afterNodeAccessメソッドを介してキューの最後に移動されていることがわかります。頻繁にアクセスされるノードはチームの最後に移動するため、チームのヘッド近くのノードは、ほとんどアクセスされない要素です。

436の元の記事が公開されました 1313の賞賛 630,000ビュー

おすすめ

転載: blog.csdn.net/qq_33589510/article/details/105459764