JDKのソース - 両端キューArrayDeque

0.はじめに

  • 退屈月曜日の夜、何もないですが、私は見てJDKのソースコードを見て、遊びにコードを探し始め、ねえ、輝く、これは彼の事の前に無視されているようです
  • タイトルを見ても、私はソースコードを見ていることを知っているArrayDeque
  • さて、私たちの予備知識(素晴らしいああ)で最初に見てみましょう、(ギャングを無視してください)がわかりません防ぐために

0.1キュー

  • まず第一に、我々は、キュー(待ち行列)であるかを知る必要がありますか?

キューは、特殊な線形形式で、それが唯一のテーブル(フロント)の前端に削除を可能にすることで特別な挿入の後端ながら、操作してキューとしてテーブル(尾部)、及びスタックリニア規制テーブル。端の後端と呼ぶ、削除操作は、ヘッドの挿入操作と呼ぶことにします。

0.2スタック

  • その後、我々は、スタック(スタック)であるかを知る必要がありますか?

スタック(スタック)は、また、動作の線形形状が制限されているスタックとして知られています。唯一のトレーラーでリニアテーブルの挿入や削除の操作を定義します。この入力は、比較的、スタックと呼ばれ、他方の端部は、スタックの底部と呼ばれます。スタックプッシュまたはプッシュに、スタックとして知られる新しい要素を挿入、それはスタックの新しいトップを作り、上記の先頭の要素に新しい要素される。つのスタックから削除要素スタックまたはとしても知られていますスタック解除、それは隣接する要素は、スタックの新しいトップになりそうという、削除最上位の要素です。

1.ソース構造

  • それはJavaのソースコードについてですので、それは確実に継承実装構造図の欠如ではありません

ArrayDeque

1.1キュー

  • キュー・インターフェースは、一般的に言って、Collectionインタフェースを拡張することで動作特性の文のキューに関連するメソッドを追加します

  • ブールアドオン(E e)は、何のスペースが利用できない場合成功し、それはIllegalStateExceptionがスローされた場合、このキューに要素に容量制限に違反することなく指定され、trueを返します。

  • ブールプラン(E e)は、このキューに要素を指定された容量の制約に違反しない場合インチ この方法を使用して添加することが一般的に好ましい場合、キュー容量が制限され、後者の缶は、例外を発生する素子を介して挿入されます。

  • E削除();

  • Eの世論調査();ああ世論調査ではまた、削除と同じプランを削除し、追加キューが空であるか、例外がスローされた場合、投票はNULLを返します。

  • E要素()。

  • EのPEEK();要素も追加のぞくと、キューは、例外がスローされ、空で、PEEKが直接バックヌルを投げていない場合は、同じ提供します。

1.2 Dectue

  • 両端キューが収集インサートの端と線形削除要素の両方でサポートされています。直訳は「ダブルエンドキュー」彼は「両端キュー」の頭字語であり、通常は「デック」と発音されます。ほとんどのリアライズが、彼らは含まれていてもよい要素の数には一定の制限はありませんが、このインターフェースは、容量に制約のコンテナとコンテナサイズの上限が固定されていないサポートしています。

  • ボイドaddFirst(E電子);キューの挿入ヘッドは、容量が不足して説明します

  • 空addLast(E e)は、キューの挿入端部は、容量が十分ではありません与えられます

  • ブールofferFirst(E e)は、キューの挿入ヘッドは、trueを返し容量が十分に成功し、偽ではありません

  • ブールofferLastと(E e)は、キューの挿入端部が、真の容量が十分に成功していない返し、偽

  • E removeFirstと/ラスト(E E)

  • 頭と尾の要素を除去し、返されたからE pollFirst /ラスト(E e)は、元Shuが戻りヌルを与えられていない前出であります

  • E getFirstと/ラスト(E e)は、

  • E peekFirst /ラスト(E E)

  • 上記従来の方法等に加えてもPEEKプッシュポップを持っています、

1.3 ArrayDeque

  • この方法の概略クラス

  • 主にキューとスタック上で動作し、参照することは困難ではありません。ここで私はクラスの実現について話を詳細にこのことについてお話します

2. ArrayDequeデータ構造

田畑

  • ArrayDeque本質は、彼がダブルエンドキューを作るために使用することができます頭と尾が含まれているデザインの配列の拡大は、(私は頭と尾のポインタを呼び出すために使用される)もスタックを作るために使用することができている、と作られた彼の実現そのスケーラビリティを確保するために(HashMapので行うにはシフト演算子を持つ)を2回膨張機構。
  • また、それはスレッドセーフではありません、それは任意のソース同期動作をしないことに注意してください。
  • 変動要素と共に増加した後、主にキャリアとして両端キューアレイは、図記録ヘッドとテールポインタを移動させることによって削除されます。

2.1コンストラクタ

    public ArrayDeque() {
        elements = new Object[16];
    }
    public ArrayDeque(int numElements) {
        allocateElements(numElements);
    }
    public ArrayDeque(Collection<? extends E> c) {
        allocateElements(c.size());
        addAll(c);
    }
    private void allocateElements(int numElements) {
        elements = new Object[calculateSize(numElements)];
    }
    private static int calculateSize(int numElements) {
        int initialCapacity = MIN_INITIAL_CAPACITY;
        // Find the best power of two to hold elements.
        // Tests "<=" because arrays aren't kept full.
        if (numElements >= initialCapacity) {
            initialCapacity = numElements;
            initialCapacity |= (initialCapacity >>>  1);
            initialCapacity |= (initialCapacity >>>  2);
            initialCapacity |= (initialCapacity >>>  4);
            initialCapacity |= (initialCapacity >>>  8);
            initialCapacity |= (initialCapacity >>> 16);
            initialCapacity++;

            if (initialCapacity < 0)   // Too many elements, must back off
                initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
        }
        return initialCapacity;
    }
复制代码
  • 図から分かるように、デフォルトの設定パラメータは、デフォルトの容量サイズは16であり、割り当てられていません

  • それは最新のインデックスの値2倍よりも大きくなりますどのように多くの要素を計算するために開発された場合

  • パスは直接セットサイズも計算能力を渡します

  • INTのデフォルト値に対応するオブジェクトを作成した後、図に示した頭部と尾部とフロント補正尾部(後部)、0です。

  • ダブルエンドキュー、フロントといつものポイントで現在のチームの最初の要素の場所へ
  • 次の位置テール(リア)は、常に最後の要素は、チームの立場であるチームを指し

2.2追加の要素法

  • それはまた、本質的に類似しているいくつかの要素のスタックを添加する方法として使用されているように両端キューのキューを使用することができるので、しかし

  • addFirstチームのヘッド要素が増加

    public void addFirst(E e) {
        if (e == null)
            throw new NullPointerException();
        elements[head = (head - 1) & (elements.length - 1)] = e;
        if (head == tail)
            doubleCapacity();
    }
    public boolean offerFirst(E e) {
        addFirst(e);
        return true;
    }
复制代码

  • この両端キューからわかるように、ヌル値を入れる方法はありません。そしてofferFirstは方法であり、addFirst

  • チームのヘッド&(elements.length - 1)から - このメソッドは、要素(1頭)を大きくすることであるため、ここで説明し、この場所は2どのくらいの電力の長さであり、そしてもし1全体の時間マイナス1つのバイナリ表現彼は自動的にでも外見場合、配列の長さ-1を配置します1つのマイナス負の後に頭に相当。この場所は、円形のキューを実現します

  • 尾の要素を高めるaddLast

    public void addLast(E e) {
        if (e == null)
            throw new NullPointerException();
        elements[tail] = e;
        if ( (tail = (tail + 1) & (elements.length - 1)) == head)
            doubleCapacity();
    }
复制代码
  • addFirst addLastメソッドに対応するofferFirstコールに似ています

  • ここでdoubleCapacityは、キューが要素を追加したときに、テールが拡大を開始するスペースの不足の前に等しい値は、次の方法の拡張を持っていることを条件と始まるこの展開について話をします

    private void doubleCapacity() {
        assert head == tail;
        int p = head;
        int n = elements.length;
        int r = n - p; // number of elements to the right of p
        int newCapacity = n << 1;
        if (newCapacity < 0)
            throw new IllegalStateException("Sorry, deque too big");
        Object[] a = new Object[newCapacity];
        System.arraycopy(elements, p, a, 0, r);
        System.arraycopy(elements, 0, a, r, p);
        elements = a;
        head = 0;
        tail = n;
    }
复制代码
  • それは尾の直後にコピーする新しい配列、0の前に長さ-1のレプリケーションにSystem.arraycopyのヘッドを使用することです。

除去要素2.3の方法

  • pollFisrt pollLastと配列要素に除去操作はまた、実質的に類似しています
    public E pollFirst() {
        int h = head;
        @SuppressWarnings("unchecked")
        E result = (E) elements[h];
        // Element is null if deque empty
        if (result == null)
            return null;
        elements[h] = null;     // Must null out slot
        head = (h + 1) & (elements.length - 1);
        return result;
    }

    public E pollLast() {
        int t = (tail - 1) & (elements.length - 1);
        @SuppressWarnings("unchecked")
        E result = (E) elements[t];
        if (result == null)
            return null;
        elements[t] = null;
        tail = t;
        return result;
    }
复制代码
  • removeLast removeFirstとofferLastとofferFirstはそれぞれ、ポーリングと呼ばれる方法に対応しています

要素2.3を得る方法

  • 二つのタイプがある要素を得る方法は、一つ取得し、アレイから除去することで、一つの要素のみを除去得られません
  • ポールの除去のために呼び出していないため、クラスから抜け出します

3. A少数の注意事項

  • 注:呼び出しを削除Eは、removeFirstとあります

  • 注:ブールのオファーコールがofferLastとあります

  • 注:ブールの追加・コールがaddLastです

  • 注:Eのポーリング呼び出しでpollFirst

  • 注:E要素がgetFirstと呼ばれています

  • 注:EのぞくコールがpeekFirstです

  • 注:コールを押して次のとおりです。addFirst

  • 注:ポップ呼び出しがremoveFirstとあります

  • 非常に単純であることができるソースコードに対応する5月上記を参照されたいです。

おすすめ

転載: juejin.im/post/5e00b06351882512416a6e51