ArrayListクラスの詳細

5476 ワード

ArrayListクラス


ArrayListはスレッドセキュリティではなく、単一スレッド環境でのみ使用可能であり、マルチスレッド環境ではCollectionsを使用することが考えられる.synchronizedList(List)

実装されたインタフェースと継承されたクラス


関数は、スレッドが安全なArrayListクラスを返します.concurrentを使用して、自動的に容量が増加するCopyOnWriteArrayListクラスを構築することもできます.ArrayListはSerializableインタフェースを実現しているので、シーケンス化をサポートし、シーケンス化伝送を通じてRandomAccessインタフェースを実現し、高速ランダムアクセスをサポートしている.実際には、反復器を使用してアクセスするよりも速く、このインタフェースは1つのタグインタフェースであり、ユーザーに何を強制することもできず、Cloneableインタフェースを実現し、クローン化することができる.リストインタフェースを実装し、最下位層は配列を使用してすべての要素を保存します.その操作は基本的に配列に対する操作である

ArrayList定義クラスの2つの重要な属性


継承された親AbstractListには、重要な属性protected transient int modCount=0があります.構造上、このリストを変更した回数.構造的に変更とは、リストのサイズを変更したり、リストを乱したりして、進行中の反復にエラーの結果を生じさせることです.反復器を使用して遍歴する場合、リスト内の要素が構造的に変化しているかどうかを確認するために使用されます(リスト要素の数が変化している)、主にマルチスレッド環境で使用する必要があります.1つのスレッドが反復遍歴していることを防止し、もう1つのスレッドがこのリストの構造を変更します.
transient Object[] elementData; // non-private to simplify nested class access
private int size;

ElementDataはコンテナの要素を保存し、sizeはコンテナ内の要素の数を指します.

3つの構造方法


//ユーザは、初期サイズがinitialCapacityの構造方法public ArrayList(int initialCapacity){}//無パラメータの構造方法を定義し、デフォルト容量は10 public ArrayList(){}//集合cを含むコンテナを初期化し、サイズもcのサイズpublic ArrayList(Collection)に等しい

エレメントストレージ


ArrayListはset(int index,E element)、add(E e)、add(int index,E element)、addAll(Collection)を提供する
public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

エレメントを追加するたびに、コンテナのサイズが十分かどうかをチェックします.エレメント配列が空の場合、コンテナはデフォルトのサイズ10で、コンテナのサイズが足りない場合は、コンテナのサイズを元の1.5倍に増加します.それでも足りない場合は、新しいコンテナのサイズは、新しく追加するエレメントまたは集合のサイズです.ここで質問があります.MAX_ARRAY_SIZE比Integer.MAX_VALUE小8.ドキュメントの説明では、一部の仮想マシンは配列にヘッダバイトを保持しており、より多くのスペースを割り当てるとメモリがオーバーフローする可能性があります.配列自体が8バイトの記憶サイズ2147483648を用いるため、記憶容量が2の31乗-8であるという解釈もある.

要素読み込み

//  。 
 public E get(int index) {  
    RangeCheck(index);  
    return (E) elementData[index];  
  }

要素の削除


//このリストで指定した場所の要素を削除します.削除した要素public E remove(int index){}//このリストに最初に表示された指定した要素が存在する場合に削除されます.これは,ArrayListに重複する要素の格納が許可されているためである.public boolean remove(Object o) { }

まとめ


保存する要素の数を予測できる場合、ArrayListインスタンスを構築するときに、配列拡張の発生を回避するために容量を指定します.あるいは、実際のニーズに応じて、ensureCapacityメソッドを呼び出すことによって、ArrayListインスタンスの容量を手動で増加させる.