はじめに
最初に、Javaのコレクション構造を2つのカテゴリに分けて簡単に説明します。1列コレクションのコレクションと2列コレクションのセットです。
単一列のコレクション:順序付けされた反復可能で、一般に変数配列と呼ばれる配列を置き換えるために使用されます
二重列コレクションマップ:
ArrayList、Vector、LinkedListの違い
ArrayList:Listインターフェースの主要な実装クラスの1つとして、スレッドは安全でなく、非常に効率的です。下部では、ストレージにObject [] elementDataを使用しています。
JDK7:
ArrayList list = new ArrayList(); //最下層が作成したObject []長さが10のelementElementData
list.add(123); // elementData [0] = new Integer(123);
...
list.add(11); //この追加により、基礎となるelementData配列の容量が不足する場合は、容量を拡張します。
デフォルトでは、容量は元の容量の1.5倍に拡張されており、元のアレイのデータを新しいアレイにコピーする必要があります。
JDK8:
ArrayList list = new ArrayList(); //基になるObject [] elementDataは{}に初期化されます。長さ10の配列は作成されません
list.add(123); // add()の最初の呼び出し時に、最下層は長さ10の配列を作成し、データ123をelementData [0]に追加しました
その後の追加および拡張操作は、jdk 7と同じです。
概要の概要:jdk7でのArrayListオブジェクトの作成はシングルトンハンガーに似ていますが、jdk8でのArrayListオブジェクトの作成はレイジーシングルトンに似ており、配列の作成を遅らせてメモリを節約します。
LinkedList:頻繁な挿入および削除操作の場合、この種の効率を使用するとArrayListよりも効率がよくなり、下部では二重にリンクされたリストストレージを使用します。
LinkedList list = new LinkedList(); Nodeタイプの最初と最後のプロパティは内部的に宣言されており、デフォルト値はnullです
list.add(123); // 123をノードにカプセル化し、ノードオブジェクトを作成します。
その中で、Nodeは次のように定義されます。LinkedListの二重リンクリストを反映するステートメント
プライベート静的クラスNode <E> {
E item;
ノード<E>次;
ノード<E> prev;
Node(Node <E> prev、E element、Node <E> next){
this.item = element;
this.next = next;
this.prev = prev;
}
}
ベクトル:Listインターフェースの古代の実装クラスとして;スレッドセーフ、低効率;下部はObject [] elementDataストレージを使用
jdk7およびjdk8のVector()コンストラクターを介してオブジェクトを作成する場合、最下層は長さ10の配列を作成します。
容量拡張に関しては、デフォルトの容量拡張は元のアレイの長さの2倍です。
ハッシュセット
HashSetの最下層は、配列とリンクリストのストレージを引き続き使用し、主に無秩序と非再現性に反映されます
要素aをHashSetに追加する場合、まず要素aのhashCode()メソッドを呼び出して要素aのハッシュ値を計算し、アルゴリズムハッシュアルゴリズムを通じてこのハッシュ値を計算して、配列内の位置iを計算します。配列内の位置iが存在しない場合要素が追加されると、a要素が正常に追加されます。要素bがi位置に存在する場合、bのハッシュ値とaのハッシュ値が比較されます。両者が異なる場合、aとbはリンクリストを使用してi位置に格納されます。 、同じものは保存されず、異なるものはリンクリストに保存されます。
HashMap
JDK7
HashMap map = new HashMap():インスタンス化の後、最下層は長さ16の1次元配列Entry []テーブルを作成します。
...複数のput操作を実行した可能性があります...
map.put(key1、value1):最初に、key1が属するクラスのhashCode()を呼び出して、key1ハッシュ値を計算します。このハッシュ値がアルゴリズムによって計算された後、エントリ配列内の格納場所を取得します。この場所のデータが空の場合、key1-value1は正常に追加されます。----状況。この場所のデータが空でない場合(つまり、この場所に1つ以上のデータが(リンクリストの形式で)存在する場合)、key1のハッシュ値と1つ以上の既存のデータを比較します。key1に希望値は既存データのハッシュ値とは異なりますが、現時点ではkey1-value1の追加に成功しています。----ケース2。key1のハッシュ値が既存のデータ(key2-value2)の1つのハッシュ値と同じである場合(ハッシュの競合)、比較を続行します。key1が配置されているクラスのequals(key2)メソッドを呼び出し、比較します。 false:key1-value1は正常に追加されました。----ケース3。equals()がtrueを返す場合:value2をvalue1に置き換えます。補足:ケース2とケース3について:この時点で、key1-value1と元のデータはリンクリストに格納されています。
連続添加工程では膨張問題が発生し、臨界値を超えた場合(かつ格納場所が空でない場合)に膨張が行われます。デフォルトの拡張方法:元の容量の2倍に拡張し、元のデータをコピーします。
:異なる態様でのHashMap jdk8 JDK7基底実装と比較して
1.新しい新規HashMapの():底層の長さ16の配列を作成されていない
配列を底2 JDK 8:なくエントリーよりもノード[]、[]
。3
。put ()メソッドが初めて呼び出されると、最下層は長さ16の配列を作成します。4. jdk7の基礎となる構造は、配列+リンクリストのみです。jdk8の基本構造:配列+リンクリスト+赤黒木。
4.1リンクリストを作成する場合は上下に移動します(jdk7:新しい要素は古い要素を指します。Jdk8:古い要素は新しい要素を指します)
4.2配列のインデックス位置にある要素がリンクリストの形で存在する場合、データ数> 8、現在の配列の長さが64より大きい場合、このインデックス位置のすべてのデータは、赤と黒のツリーを使用して格納されます。
赤黒木
ハッシュの競合の問題を解決するために、つまり、長いリンクリストがハッシュ値の下でハングするため、jdk1.8では、HashMapの最下層は配列、リンクリスト、および赤黒木で構成されます。 「バランス」とは、非常に長いサブツリーがないことを意味します。
赤黒木のいくつかの特徴:
(1)ノードは赤または黒です
(2)ルートノードは黒でなければなりません
(3)リーフノードは黒いNullノードである必要があります
(4)各赤のノードの2つの子ノードは黒でなければならない
(5)ツリー内の任意のノードから各リーフノードへのパスに、同じ数の黒いノードが含まれている
赤黒木は自己バランスの3つの魔法の武器を保証できます:左利き、右利き、変色
左回転:回転ノードの右ノードは親ノードであり、右ノードの左サブツリーは回転ノードの右サブツリーとして使用されます
右回転:回転ノードの左ノードが親ノードになり、左ノードの右サブツリーが回転ノードの左サブツリーになります
変色: