アウトライン
ArrayListのダイナミックアレイは、ArrayListの要素が空であることができ、それを繰り返すことができる基盤の非スレッドセーフな実装のコレクションであり、それはまた、(シーケンシャルリードと一致して記憶)命じています。
ArrayListのAbstractList継承、リスト、ランダム・(高速アクセス)を達成するために、Cloneableを(クローンであってもよい)、java.io.Serializableの(支持シリアライゼーション)は、以下のソースコードの断片です。
初期化
次の3つの方法のArrayListの初期化:
- 1、私たちが使用する初期化メソッドまでの引数なしのコンストラクタ、10のデフォルトの長さ:
/ ** * 10の初期容量で空のリストを作成します。 * / 公共のArrayList(){ この .elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA。 }
今回、我々はソースコードから見ることができ、コードの唯一の行があります:this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA、DEFAULTCAPACITY_EMPTY_ELEMENTDATAは、そのように定義され、ソースコード中に見つけることができます:
/ ** *デフォルトのために使用される共有空の配列のインスタンスは、空のインスタンスをサイズ設定しました。我々 *とき膨らませるためにどのくらい知っているEMPTY_ELEMENTDATAからこれを区別する *最初の要素が追加されます。 * / プライベート 静的 最終オブジェクト[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
ソースコードは、デフォルトのサイズとして空の配列を定義し、次いで、アレイ要素の数が出てきた最初の膨張中に添加される決定にコメントすることによって知ることができる、このロジックは、次のセクションの添加元素に説明します。
- 図2に示すように、指定された長さを初期化します。
/ ** *指定された初期容量で空のリストを作成します。 * @param InitialCapacityのリストの初期容量 * @throws はIllegalArgumentException指定された初期容量であれば *マイナスであります * / 公共のArrayList(INT InitialCapacityの値){ 場合(InitialCapacityの値> 0 ){ この .elementData = 新しいオブジェクト[InitialCapacityの値]。 } そう であれば(InitialCapacityの値== 0 ){ この .elementData = EMPTY_ELEMENTDATA。 } 他{ スロー 新しい例外:IllegalArgumentException( "不正な容量:" + InitialCapacityの値を)。 } }
- Collectionオブジェクトで構成さ3、
/ ** *指定の要素を含むリストを作成 彼らはコレクションのによって返される順序で*コレクション、 *イテレータ。 * * @param 要素であり、このリストの中に配置されるコレクションC * @throws 指定されたコレクションがnullの場合、NullPointerExceptionが * / 公共のArrayList(コレクション<?拡張 E> {C) elementData = c.toArray()。 もし((サイズ= elementData.length)!= 0 ){ // c.toArrayのかもしれない(間違って)(6260652を参照してください)] [オブジェクトを返さない 場合(elementData.getClass()!=オブジェクト[]。クラス) elementData = Arrays.copyOf(からelementData、サイズ、オブジェクト[]。クラス)。 } 他{ // 空の配列と交換してください。 この .elementData = EMPTY_ELEMENTDATA。 } }
要素を追加します
リストの要素を追加するには、Addメソッドを提供し、我々は、コードのこの部分にソースコードを見て:
/ ** *このリストの最後に、指定された要素を追加します。 * * @paramのE要素がリストに追加されます * @return <TT>真</ TT>({によって指定さ@link コレクション#アドイン}) * / パブリック ブール追加(E E){ ensureCapacityInternal(サイズ + 1)。 // インクリメントmodCount !! elementData [サイズ++] = E。 返す 真; }
elementData [サイズ++] = Eの前に、ensureCapacityInternal(サイズ+ 1)、この展開方法は、一時的に無視するように、添加元素をからelementDataの位置に追加され、本明細書中で、含むであろう次のものがあります要素を参照します。
拡張
上記のコードでは、我々は法ensureCapacityInternal()、パラメータが渡されると述べたサイズ+ 1(サイズのArrayListは、要素の数が所有しています)、私たちは今、この特定の方法を見てみましょう:
プライベート 無効 ensureCapacityInternal(int型minCapacityに){ 場合(==からelementData DEFAULTCAPACITY_EMPTY_ELEMENTDATA){ minCapacityに = Math.max(DEFAULT_CAPACITY、minCapacityに)。 } ensureExplicitCapacity(minCapacityに)。 }
ストレージアレイは、間およびサイズ+ 1の最大値(デフォルト容量は10である)を空の配列、DEFAULT_CAPACITYに最小容量であり、これは最初の添加元素であれば、今、我々は、振り返ると思われる場合、 minCapacityには、その後、10になり、この場合に割り当てられている、すなわち、引数なしのコンストラクタは、長さが10のArrayListである場合。
次の実行ensureExplicitCapacity(minCapacityに)、我々はソースをフォローアップしていき:
プライベート 無効 ensureExplicitCapacity(int型minCapacityに){ modCount ++ ; // オーバーフロー意識コード 場合(minCapacityに- elementData.length> 0 ) (minCapacityに)成長。 }
modCountはそれが詳細に説明されていない、それは安全側故障イテレータは、この問題は、例外がスローされますことを発見した場合は、これがポイントではありません、回数に変更のセットをカウントします。
上記の手順は、アレイの容量よりも大きいminCapacityには、得られた(最小容量)である場合、それは成長、は、以下の拡張を行う必要があります。
/ ** *それは、少なくとも保持できることを保証するために容量を増やし *最小容量引数で指定した要素の数。 * * @param minCapacityに所望の最小容量 * / プライベート ボイドが成長(INT minCapacityに){ // オーバーフロー意識コード INT oldCapacity = elementData.length。 INT newCapacity = oldCapacity +(oldCapacity >> 1 )。 もし(newCapacity - minCapacityに<0 ) newCapacity = minCapacityに。 もし(newCapacity - MAX_ARRAY_SIZE> 0 ) newCapacity = hugeCapacity(minCapacityに)。 // minCapacityには通常に近い大きさにあるので、これは勝利です: からelementData = Arrays.copyOf(からelementData、newCapacity)。 }
OldCapacity元の容量は、アレイ、拡張後の新しい配列newCapacity能力として定義される
新しい容量oldCapacity +(oldCapacity >> 1)、シフト動作により、1.5倍に拡大されoldCapacity 1.5倍、1.5倍開発者は、時間と空間で撮影された値を量ります。計算された容量が少ない新しい最小容量が必要以上にある場合には、最小サイズは新しい容量を置くために設定されています。
以下の比較は、プロセス(非常にまれなケース)は、特に大容量により行われます。
次のように最後に、アレイ内の要素は、新しい配列への配列のオリジナルの要素からコピーされます。
パブリック 静的 <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))。 戻り値のコピー。 }
配列内の要素の順序を変更し、アレイは新しい要素の位置が空でないです。
要素を削除します
- 1、添字によって要素を削除します。
/ ** *このリスト内の指定された位置にある要素を削除します。 *彼らから1減算(後続の要素は左に移動 *インデックス)。 * * @paramの要素のインデックスを削除するインデックス * @return リストから削除された要素 * @throws はIndexOutOfBoundsException { @inheritDoc } * / パブリック E削除(int型の{指標) rangeCheck(インデックス)。 modCount ++ ; E OLDVALUE = からelementData(インデックス) int型 numMoved =サイズ-インデックス- 1 。 もし(numMoved> 0 ) System.arraycopyの(からelementData、インデックス +1 、からelementData、インデックス、 numMoved); elementData [ --size] = NULL ; // GCはその作業をやらせることが明らか 返すOLDVALUEを。 }
あなたは要素の位置は、配列の長さよりも大きい削除したい場合はまず、削除チェックは、それが添字境界例外を報告します。
すべての要素の背面から移動、削除され、プロセスは、全体として前方System.arraycopyの()で要素を指定し、最終的には要素の端部は、GCの回復を待って、nullに設定されています。
それは前方位置コピーの背後にある要素のすべての要素を必要とするためのArrayListが不安定なので、削除のパフォーマンスは、より多くのあなたが悪く、性能、要素をコピーします。
2、あなたが同じ添字て削除すると、オブジェクト、プロセスおよび原理を削除することによって、本明細書中に記載されていません。
添字によって挿入
単に末尾に要素を追加し、パフォーマンスは悪くないですが、パフォーマンスが不安定であるように、指定された場所に要素を追加します。
/ ** *挿入し、この内の指定された位置に指定された要素 *リスト。シフトその位置で現在の要素(もしあれば)と 右に*後続の要素(インデックス値に1を加算)。 * * @paramの指定された要素が挿入されるインデックスindex * @paramの要素要素が挿入されます * @throws はIndexOutOfBoundsException { @inheritDoc } * / 公共 ボイド追加(int型のインデックス、E要素){ rangeCheckForAdd(インデックス)。 ensureCapacityInternal(サイズ + 1)。 // インクリメントmodCount !! System.arraycopyの(からelementData、インデックス、からelementData、インデックス+ 1 、 サイズ - インデックス)。 elementData [インデックス] = 要素; サイズ ++ ; }
まず、実行、チェックを追加するには、場所は、配列の長さよりも大きい追加した場合、それは添字の境界例外を報告します。
最も重要な点は次のとおりです。指定された場所にあるアドオンは、我々はあなたが要素を追加したい終え、System.arraycopyのことによって達成され、その要素の位置に設定されている、すべての全体としての要素が一つの位置戻され、この位置をバックアップする必要がありますこの場合には、パフォーマンスが不安定で、より多くのあなたは、要素、より悪いパフォーマンスを移動したいです。
要素の検索
要素が非常にシンプルに見えます:
/ ** *このリスト内の指定された位置にある要素を返します。 * * @paramの 復帰への要素のインデックスindex * @return このリスト内の指定された位置にある要素を * @throws はIndexOutOfBoundsException { @inheritDoc } * / 公共 EのGET(int型のインデックス){ rangeCheck(インデックス)。 リターンからelementData(インデックス); }
これは、複雑な操作、ダイレクトリターン位置の要素を、非常に良好なパフォーマンスを必要としません。
概要:
このプロセスを介してソース出発、ArrayListの初期設定の詳細な分析、さらに、拡張、削除プロセスからのこの記事では、我々は明確に理解することができます:
1、それは達成するために、アレイを介しているので、添字によって直接要素を見つけることができ、かつ実装ランダム・インタフェースのアクセス速度を高速化するために、非常に高速であるルックアップArrayListの要素;
2は、単純な最初の決定、プロセスは非常に単純で、要素を追加します膨張が関与し、そして次いで直接要素のような尾を添加すること;
3、要素を削除する要素の位置のすべての後の完全なコピーを含む、不安定は、非常に悪いものと理解することができます。