原理とソースコード解析の実現にJDK1.8のArrayListを

I.概要

             ArrayListのJavaはより頻繁にクラスの開発に使用されている私たちは、プログラミングの際に利用できるように、ソースコードの解釈を通じて、我々は、その利点と欠点をクリアし、ArrayListの内部構造と実装を理解することができます。

第二に、ソースコード解析

2.1クラス構造

 ArrayListにクラスの構造定義JDK1.8ソース次のように:

パブリッククラスのArrayList <E>はAbstractList <E>が延び
一覧<E>、ランダム・、Cloneableを、java.io.Serializableの実装
其中を:

Listインタフェースは、キュー配列は、基本的なCRUDリスト機能を持つ実装
ランダムアクセスRandomAccessインタフェースの機能をすることができます実現
Cloneableインタフェースを実現するクローニングすることができる
、Serializableインタフェースを実装し、シリアライズとデシリアライズ方法を書き換えますより良いパフォーマンスシリアライズがありArrayListの
2.2メンバ変数といくつかの工法を 

/ **
*主に示すために、シリアライゼーションIDを定義する異なるバージョンの互換性
* /
プライベートロングのserialVersionUID =最終静的8683452581122892189L;

/ **
*配列(ArrayListの基礎となる構造体の配列)のデフォルトの記憶容量
* /
民間最終静的10 DEFAULT_CAPACITY = INT;

/ **
*指定された配列の能力ゼロ定数値使用している
* /
[] = {}プライベート静的EMPTY_ELEMENTDATA最終的なオブジェクトを;

/ **
デフォルトのコンストラクタのパラメータ空間を使用して*定数値
/ *
最終的な静的オブジェクトプライベート[] = {} DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

/ **
データのオブジェクトの配列*実記憶、過渡識別子がシリアル化されていない
* /
一時オブジェクトの[]からelementData; //プライベートアクセス非入れ子になったクラスを簡素化

/ **
*以下elementData.lengthに等しい配列内の要素の実数
* /
プライベートint型のサイズ;
/ **
*変更番号
* /
保護ModCount過渡INT = 0;

/ *
*コンストラクタ:容量の大きさを指定
* @param InitialCapacityの値
* /
公共のArrayList(INT InitialCapacityの値){
/ *
*どのくらいの容量を指定しどのくらいの容量である
* /
IF(InitialCapacityの値> 0){
this.elementData =新しい新しいオブジェクト[InitialCapacityの値];
}そうIF(InitialCapacityの値== 0){容量の大きさが指定されていない//、空の配列
this.elementData = EMPTY_ELEMENTDATA;
} {他
スロー新しい新はIllegalArgumentException( "無効な容量:" +
InitialCapacityの値);
}
}

/ **
*コンストラクタII:空のデフォルトの参照コンストラクタ
* /
公共のArrayList(){
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA。
}

/ **
*构造函数三:传入集合参数的构造函数
*
*要素であり、このリストの中に配置されるコレクションC @param
指定されたコレクションがnullである場合* @throws NullPointerExceptionが
* /
公共のArrayList(コレクション< ?E> C){延び
からelementData =(?(のArrayList <>)C).toArray();
((サイズ= elementData.length)!= 0)の場合{
// c.toArrayが(間違って)オブジェクト[](6260652を参照)を返さないかもしれません
(elementData.getClass()!=オブジェクト[]。クラス)の場合
からelementData =配列.copyOf(からelementData、サイズ、オブジェクト[]クラス);
}他{
//空の配列と交換してください。
this.elementData = EMPTY_ELEMENTDATA。
}
}
2.3常用方法

(E eを)追加し、関連メソッド:ArrayListの要素をに追加された
/ **
指定されたが、この要素リストの最後に追加します*。
*
* @Param E要素のリストに追加される
/ <trueに* @return <TT> TT>(追加で指定された{@linkコレクション#})
* /
パブリックブールの追加(E E){
ensureCapacityInternal(サイズ+ 1); //インクリメントModCount !!
[サイズ++] = EのからelementData;
真に戻る;
}
プライベート無効ensureCapacityInternal(intはminCapacityにすること){
/ **
次に大きい方デフォルトの追加数(10)を比較すると、比較*空の配列の元の数であれば、
* /
IF(DEFAULTCAPACITY_EMPTY_ELEMENTDATAの==からelementData){
minCapacityに= Math.maxことを(DEFAULT_CAPACITY、minCapacityにすること);
}

ensureExplicitCapacity(minCapacityにすること);
}
ボイドensureExplicitCapacityプライベート(intはminCapacityにすること){
ModCount ++;

/ **
*配列の実際の長さと1後の電流大小関係の長さを加えた配列内の要素の数を決定し、0未満である、戻り、0より大きい場合、
*成長コール(minCapacityに)メソッド
* /
IF(minCapacityにする- elementData.length> 0)
(minCapacityにすること)成長;
}
/ **
*これに容量が増加ITをEnsure®得る少なくともHOLD
要素の*数引数で指定された最小容量。
*
* @paramはminCapacityにすること所望の最小容量
* /
プライベートボイド{(intはminCapacityにすること)成長
//オーバーフロー配慮コード
; INT = oldCapacity elementData.length
INT = oldCapacity newCapacity +(oldCapacity >> 1); //容量は、元の1.5倍となる
場合( newCapacity - minCapacityに<0)
newCapacity = minCapacityに。
IF(newCapacity - MAX_ARRAY_SIZE> 0)
newCapacity = hugeCapacity(minCapacityに)。
// minCapacityには、サイズに通常近いので、これは勝利です:
からelementData = Arrays.copyOf(からelementData、newCapacity)。
}
パブリック静的<T、U> T [] copyOf(U []原、INT newLength、クラス<?T []延び>
ニュータイプ)を{
@SuppressWarnings( "未チェック")
T []はコピー=((オブジェクト)ニュータイプ= =(object)オブジェクト[]。クラス)
(T [])新しいオブジェクト[newLength]
:(T [])Array.newInstance(newType.getComponentType()、newLength)。
System.arraycopyの(元の、0、コピー、0、
Math.min(original.length、newLength))。
コピーを返します。
}
分析: 

第さもなければ第二メソッドを呼び出し、番号が大きい方、デフォルト(10)に追加された場合、現在の配列が空の配列、数を比較するコンパレータであるか否かを決定する方法でensureCapacityInternal(サイズ+ 1)の方法。
最初modCount + 1であるensureExplicitCapacity(INT minCapacityに)方法、0未満の場合、、、大小関係1の後に戻る配列要素の数と現在の配列長の真の長さを決定し、0より大きい場合、方法は、3と呼ばれています。
oldCapacity +(oldCapacity >> 1)現在の配列の長さを使用して成長させる(minCapacityに)メソッドは、1.5倍の膨張後の長手方向の拡張の上限値と比較して、元の、およびとなる、方法4は、呼び出し。
Arrays.copyOf(からelementData、newCapacity)メソッドは、この方法は、基礎となるSystem.arraycopyの(元は、0、コピー、呼び出すことです 0、
                         Math.min後(original.lengthは、newLength))法、古いデータはデータ拡張にコピーされます新しい配列の内部、および新しい配列を返し
、その後、新たな要素が+ 1位内側拡張後のサイズに割り当てられている追加。
   挿入要素の位置を指定するには(int型idnex、Eの要素)を追加し
、以下のようにソース。

追加パブリック(INTインデックス、E要素){無効
rangeCheckForAdd(インデックス);

ensureCapacityInternal; //インクリメントModCount !!(サイズ+ 1)
System.arraycopyの(インデックスのからelementData、,. 1 +指数、のからelementData
サイズ-指標)
のからelementData [インデックス] =要素;
サイズ++;
}
実質的ソースから見ることができるが、追加(E e)の方法と一致し、主な違いは、コードの行を増加させることである。System.arraycopyの(からelementData、インデックスからelementData 、指数+ 1、サイズ- インデックス)、およびインデックス+ 1の開始位置の完全なコピーから開始位置後のインデックスデータ、および、新しいデータがインデックス位置に追加され、データを移動する必要はありません前に。(これらのアクションの比較消費性能)

java.lang.System.arraycopy次のようにパラメータは、(オブジェクトSRC、INT srcPos、オブジェクトDESTは、destPos、INT長INT)。

(元の配列は、開始位置、開始位置、標的配列、元の標的配列の配列、コピー数)

(添字の要素を除去しに従ってとして除去)除去
ソースコードは、以下:

Eパブリック(INTインデックス){削除
rangeCheck(インデックス);
回//レコードは変更
ModCount ++と、
OLDVALUEのE =からelementData(インデックス);
//要素の数が移動する取得
int型のサイズ= numMoved -索引- 1;
IF(numMoved > 0)
,. 1 +指数のSystem.arraycopyの(からelementDataのからelementData、インデックス、
numMoved);
//サイズ-1位がnull要素を割り当て、GC回復促進
のからelementDataを[ -サイズ] = NULL;


OLDVALUEを返します;
}
ブールパブリック(オブジェクトO)を除去{
IF(O == NULL){
用(INTインデックス= 0、インデックス<サイズ、インデックス++)
IF(のからelementData [インデックス] == NULL){
fastRemove(インデックス);
真に戻ります;
}
} {他
(INTインデックス= 0、インデックス<サイズ;インデックス++)のために
IF(o.equalsの(からelementData [インデックス])){
fastRemoveは(インデックス);
真に戻る;
}
}
偽に戻り;
}
この方法は、正確に逆の操作で削除して追加し、一つの要素を削除するには、桁数に影響を与えます位置は、それはまた、より多くの消費性能です。コアコードがjava.lang.System.arraycopy呼ばれる(オブジェクトSRC、INT srcPos、オブジェクトDEST、destPosをINT、INT長) 方法

照会
公共GET Eを(int型のインデックス){
/ **
*境界かどうかを確認してください
* /
rangeCheck(インデックス);
/ **
*は、要素上の指定された位置を返す
* /
(インデックス)の返すからelementDataを;
}
//アクセス動作位置

@SuppressWarnings( "未チェック")
E(INTインデックス)のからelementData {
[インデックス]のリターン(E)からelementData;
}
変更
パブリックEのSET(INTインデックス、E素子){
/ **
*境界かどうかをチェック
* /
rangeCheck(指数);
/ **
*要素の古い値を取得します
* /
OLDVALUEのE =からelementData(インデックス);
/ **
*新しい割り当て要素
* /
[インデックス]のからelementData =要素;
/ **
*要素の古い値を返す
* /
OLDVALUEを返します。
}
クリアメソッド
クリア(){公共ボイド
ModCountが++;

//各要素はnullに、便利なGCの回復
のために(INT I = 0; Iサイズ<; Iは++)
のからelementData [I] = NULL;

サイズ= 0;
}
 もし含む
公共ブールを含み(オブジェクトO){
;(O)> = 0のindexOfを返す
}
のindexOf(物体O)INT公共{
IF(O == NULL){
ため(INT I = 0; Iサイズ<; I ++の)
IF( [I] == NULL)のからelementData
リターンI;
}他{
(I = 0 int型; Iは、サイズ<; I ++の)ため
(o.equals([I]のからelementData IF))
リターンI;
}
戻り-1;
}
この方法2例:ヌルおよび非ヌル値のトラバーサルは、クエリが割出し位置に戻る場合、それ以外の場合は-1を返し、次いで0と比較して、存在しない場合0未満、0よりも大きいがあります。

第三に、要約

      素子効率及びランダム・アクセス・トラバーサルの効率は比較的高いが、追加された要素は、アレイベースのリストの実装の場所を指定したり、指定された位置が比較的低い削除します。
---------------------

おすすめ

転載: www.cnblogs.com/ly570/p/11257592.html