Javaコレクション・シリーズ(2):ArrayListを、LinkedListは、ベクトルとの違いを使用

主ベクトルと3の方法を使用してLinkedListの間Listインタフェースの実装クラスのArrayList差の3、上のこのブログ。

1. ArrayListの使用

ArrayListのリストインターフェースは、内部配列によって達成最も一般的な実装クラスであるので、その利点は、ランダム探索とトラバースするのに適している、不利な点は、挿入および削除には適していません。

ArrayListのクラス宣言のコードは次のとおりです。

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    ......
}

1.1の追加要素

使用ArrayListの要素は、以下の2つのオーバーロードがあります追加しました:

boolean add(E e);
    
void add(int index, E element);

boolean add(E e);これは、コレクションの最後に要素を追加することで、

void add(int index, E element);これは、指定されたインデックス位置(インデックスは0から始まる)に要素を追加することです。

次のように使用します。

List<String> platformList = new ArrayList<>();

// 添加元素
platformList.add("博客园");
platformList.add("掘金");
platformList.add("微信公众号");

// 添加重复元素,会添加成功,因为List支持添加重复元素
platformList.add("博客园");
platformList.add("掘金");


platformList.add(3, "个人博客");

1.2要素を取得します

方法の要素の指定したインデックスのArrayListを取得し、以下のとおりです。

System.out.println("索引为3的元素为:" + platformList.get(3));

指定されたインデックスがコレクションの最大のインデックスを、超えた場合などは、platformList.get(6)例外がスローされますjava.lang.IndexOutOfBoundsException

1.3要素のセット数を取得します。

次のようにしているのArrayList方法の要素の数を取得します。

System.out.println("platformList的元素个数为:" + platformList.size());

1.4の要素を削除します

以下の2つのオーバーロードを使用してArrayListの削除要素:

E remove(int index);

boolean remove(Object o);

E remove(int index);要素の指定したインデックスでコレクションを削除することです、boolean remove(Object o);それは、コレクション内の指定した要素を削除することです。

次のように使用します。

// 指定索引删除重复的元素 "博客园" "掘金"
platformList.remove(4);
platformList.remove(4);
// 删除指定元素 "个人博客"
platformList.remove("个人博客");

1.5要素を変更

以下の方法を使用して、指定されたインデックス値に要素を変形のArrayList。

platformList.set(0, "博客园:https://www.cnblogs.com/zwwhnly/");
platformList.set(1, "掘金:https://juejin.im/user/5c7ce730f265da2dca388167");
platformList.set(2, "微信公众号:申城异乡人");

1.6セットが空であるか否かを判断します

ArrayListのは、空には、次のように使用するかどうか決定されています。

System.out.println("isEmpty:" + platformList.isEmpty());

1.7横断要素(よくあるインタビュー)

主に次の3通りの方法でのArrayListの要素をトラバース:

  1. 反復処理
  2. forループ
  3. foreachループ

次のように使用します。

System.out.println("使用Iterator遍历:");
Iterator<String> platformIterator = platformList.iterator();
while (platformIterator.hasNext()) {
    System.out.println(platformIterator.next());
}

System.out.println();
System.out.println("使用for循环遍历:");
for (int i = 0; i < platformList.size(); i++) {
    System.out.println(platformList.get(i));
}

System.out.println();
System.out.println("使用foreach遍历:");
for (String platform : platformList) {
    System.out.println(platform);
}

1.8空のコレクション

すべての要素を使用して、空のArrayList方法は次のとおりです。

platformList.clear();

1.9完全なサンプルコード

次のようにいくつかは、完全なコードは、上記で説明しています:

public static void main(String[] args) {
    List<String> platformList = new ArrayList<>();

    // 添加元素
    platformList.add("博客园");
    platformList.add("掘金");
    platformList.add("微信公众号");

    // 添加重复元素,会添加成功,因为List支持添加重复元素
    platformList.add("博客园");
    platformList.add("掘金");


    platformList.add(3, "个人博客");

    System.out.println("索引为3的元素为:" + platformList.get(3));
    System.out.println("platformList的元素个数为:" + platformList.size());

    // 指定索引删除重复的元素 "博客园" "掘金"
    platformList.remove(4);
    platformList.remove(4);
    // 删除指定元素 "个人博客"
    platformList.remove("个人博客");

    System.out.println("platformList的元素个数为:" + platformList.size());

    platformList.set(0, "博客园:https://www.cnblogs.com/zwwhnly/");
    platformList.set(1, "掘金:https://juejin.im/user/5c7ce730f265da2dca388167");
    platformList.set(2, "微信公众号:申城异乡人");

    System.out.println("isEmpty:" + platformList.isEmpty());

    System.out.println("使用Iterator遍历:");
    Iterator<String> platformIterator = platformList.iterator();
    while (platformIterator.hasNext()) {
        System.out.println(platformIterator.next());
    }

    System.out.println();
    System.out.println("使用for循环遍历:");
    for (int i = 0; i < platformList.size(); i++) {
        System.out.println(platformList.get(i));
    }

    System.out.println();
    System.out.println("使用foreach遍历:");
    for (String platform : platformList) {
        System.out.println(platform);
    }

    System.out.println();

    // 清空集合
    platformList.clear();
    System.out.println("isEmpty:" + platformList.isEmpty());
}

出力は次のようになります。

3インデックス要素は次のとおりです。個人的なブログ

PlatformList要素の数は、6

PlatformList要素の数は次のとおりです。3

isEmpty:偽

横断するIteratorを使用します。

パークブログ:https://www.cnblogs.com/zwwhnly/

ナゲッツ:https://juejin.im/user/5c7ce730f265da2dca388167

マイクロチャンネル公共数:上海ストレンジャー

ループ反復するために使用します。

パークブログ:https://www.cnblogs.com/zwwhnly/

ナゲッツ:https://juejin.im/user/5c7ce730f265da2dca388167

マイクロチャンネル公共数:上海ストレンジャー

foreachのトラバーサルを使用します。

パークブログ:https://www.cnblogs.com/zwwhnly/

ナゲッツ:https://juejin.im/user/5c7ce730f265da2dca388167

マイクロチャンネル公共数:上海ストレンジャー

isEmpty:真

2. LinkedListの使用

リストLinkedListのインタフェースの実装クラスは、それが動的に要素を挿入および除去のための利点であるので、欠点は、ランダムに見出され、より遅いトラバースされ、データを格納するために内部的にリンクされたリスト構造を用いています。

LinkedListのクラス宣言のコードは次のとおりです。

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
}

で宣言されたコードにArrayListをLinkedListのクラスと基本的に同じ、唯一の変更を使用します。

List<String> platformList = new LinkedList<>();

3.ベクトルの使用

ベクターはまた、インタフェースの実装クラスを一覧表示し、内部アレイによって実現されます。

次のようにVectorクラスコードが宣言されます。

public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
}

違いは、ArrayListには、ベクターは、同時に複数のスレッドが、ベクタを書く矛盾を書くことが原因としながら、マルチスレッドを避けることができ、スレッドセーフであるということです。しかし、それはまた、ベクターの不利益が生じた:その速度は、ArrayListのいくつかのより遅くなりますので、スレッドの追加支出に必要な同期を実現します。

ベクターは、ArrayListのは、マルチスレッド環境の実装のバージョンで考慮することが可能です。

したがって、コードのベクトルクラスのArrayListの使用と本質的に同じ、唯一の変更はで宣言します。

List<String> platformList = new Vector<>();

次のように伴うサポートスレッド同期に、非常に多くの方法Vectorクラスは、キーワードを同期しています:

public synchronized boolean isEmpty() {
    return elementCount == 0;
}

public synchronized int size() {
    return elementCount;
}

public synchronized void addElement(E obj) {
    modCount++;
    ensureCapacityHelper(elementCount + 1);
    elementData[elementCount++] = obj;
}

4. ArrayListに、LinkedListは違い、ベクター社(よくあるインタビュー)

注意:次のコードは、JDKのバージョンを使用しています1.8.0_191

4.1類似点

ArrayListの、LinkedListのは、ベクターは、Listインタフェースを実装するので、これを見つけることができ、上記の例により、使用に類似しています。

4.2の違い

しかし、ArrayListに、異なるLinkedListは、ベクター社の内部実装では、それはそれらの間に差があるつながります。

4.2.1ストレージ構造

ArrayListのとベクトルは、アレイベースの実装である、LinkedListのは、二重にリンクされたリストに基づいて実施されます。

要素の動的挿入や削除のためのLinkedListのが適しているがこれはまた、ランダム探索とトラバーサルのためにArrayListにつながりました。

配列や二重リンクリストについては、ここで説明するのではなく、フォローアップは、別の記事の要約を書きます。

4.2.2スレッドの安全性

ArrayListのとLinkedListのは、スレッドセーフではありません、ベクターは、スレッドセーフです。

ベクターArrayListにも効率化につながった別の実装のマルチスレッド環境で見ることができArraykListベクトルとLinkedListは高くありません。

あなたは、並行環境でのArrayListやLinkedListのを使用している場合は、コレクションクラスのsynchronizedList()メソッドを呼び出すことができます。

Collections.synchronizedList(platformList);

4.2.3膨張機構

ArrayListのとベクトルArrayListのデフォルト容量が0である、デフォルトの容量は10ベクトルであり、データを格納するのにObject型の配列を使用しています。

空の噂、我々は例のArrayListを使用して見てください:

List<String> strArrayList = new ArrayList<>();

for (int i = 0; i < 20; i++) {
    strArrayList.add(String.valueOf(i));
}

ソースArrayListのコンストラクタは次のようになります。

transient Object[] elementData;

public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

ベクターを使用して、サンプルを見てください:

List<String> strVector = new Vector<>();

for (int i = 0; i < 30; i++) {
    strVector.add(String.valueOf(i));
}

ソースベクトルのコンストラクタは次のようになります。

protected Object[] elementData;
protected int capacityIncrement;

public Vector() {
    this(10);
}

public Vector(int initialCapacity) {
    this(initialCapacity, 0);
}

public Vector(int initialCapacity, int capacityIncrement) {
      super();
      if (initialCapacity < 0)
          throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
      this.elementData = new Object[initialCapacity];
      this.capacityIncrement = capacityIncrement;
}

要素は、両方のタイプに追加された場合、容量が十分でない場合、拡張が実行され、膨張の性質は、新しいアレイを製造新しい配列に元のデータ配列をコピーし、新しい配列に新しい要素を追加することで、この方法は、使用さArrays.copyOf()れた膨張後の容量は1.5倍前の2回の場合に拡張した後、前のベクトルのデフォルトの容量をArrayListのです

ArrayListのは、やはり上記の例を使用します。

List<String> strArrayList = new ArrayList<>();

for (int i = 0; i < 20; i++) {
    strArrayList.add(String.valueOf(i));
}

実行後List<String> strArrayList = new ArrayList<>();、ケースstrArrayList容量は、0であります

そしてその後、最初の要素の追加は、strArrayList膨張容量は、10の容量である場合

11の元素の添加は、strArrayList拡張容量15の容量がある場合、

16の元素の添加は、strArrayList拡張容量22の容量がある場合、

> 49 - 拡張を必要に応じて、拡張は33に変わります。

ソースコードでのArrayListの外観は、私がなぜこの拡張を理解します:

private static final int DEFAULT_CAPACITY = 10;

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

private static int calculateCapacity(Object[] elementData, int minCapacity) {
     if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
         return Math.max(DEFAULT_CAPACITY, minCapacity);
     }
     return 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);
}

コードコアであるint newCapacity = oldCapacity + (oldCapacity >> 1);拡張後の容量は前の1.5倍のArrayListにあるように、。

上記の例では、ベクトルの外観:

List<String> strVector = new Vector<>();

for (int i = 0; i < 30; i++) {
    strVector.add(String.valueOf(i));
}

実行後List<String> strVector = new Vector<>();、ケース10はstrVector容量であり、

11の元素の添加は、strVector拡張容量20の容量がある場合、

21の元素の添加は、strVector拡張容量40の容量がある場合、

> 160 - あなたはまた、拡張が必要な​​場合は、80に拡大が続きます。

ソースコードのベクトル見て、あなたはなぜ、この拡張を理解します:

public synchronized void addElement(E obj) {
    modCount++;
    ensureCapacityHelper(elementCount + 1);
    elementData[elementCount++] = obj;
}

private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

private void grow(int minCapacity) {
     // overflow-conscious code
     int oldCapacity = elementData.length;
     int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                      capacityIncrement : oldCapacity);
     if (newCapacity - minCapacity < 0)
         newCapacity = minCapacity;
     if (newCapacity - MAX_ARRAY_SIZE > 0)
         newCapacity = hugeCapacity(minCapacity);
     elementData = Arrays.copyOf(elementData, newCapacity);
}

コアコードはint newCapacity = oldCapacity + ((capacityIncrement > 0) ?capacityIncrement : oldCapacity);、デフォルトは2回前にした後、ベクターにおける容量拡張。

4.2.4効率性

ArrayListのランダム探索及びトラバーサル効率が高くなるが、要素の動的挿入および欠失の効率が低くなります。

挿入および削除要素が動的効率が高くなるが、ランダム探索と効率を横断するLinkedListの低いであろう。

あなたはマルチスレッドでの要素のコレクションを操作する必要がある場合は、ベクトルを使用することが推奨され、それ以外の場合は、ArrayListのを使用することをお勧めします。

ソースおよび基準

違いとArrayListの、LinkedListは、ベクターの原則を実現

Javaの深さ - Javaのコレクションの深い理解

ArrayListに、ベクトルとLinkedListの類似点と相違点の高度なJavaの(四〇から六)説明

6.最後に

少し宣伝を再生し、マイクロチャンネルスキャンコード番号の公衆に焦点を歓迎:私たちは一緒に進行するように、Javaテクノロジ乾燥品を共有するために定期的に「上海は見知らぬ人です」。

おすすめ

転載: www.cnblogs.com/zwwhnly/p/11265599.html