第8章ArrayListとLinkedListの使用の分析

序文

インタビュアーからよく聞かれる質問は、ArrayListとLinkedListの違いは何ですか?
Baidu:ArrayListとLinkedListの違いは何ですか?たくさんあります。
これは決まり文句であり、それについてただで話すことに飽きることのない質問です。この章は学習の章として機能し、将来このトピックを分析します。
ArrayListとLinkedListに関する私の意見。
前の2つの章のソースコード分析アドレスは次の
とおりです第6章:JAVAコレクションのArrayListソースコード分析
第7章:JAVAコレクションのLinkedListソースコード分析

分析は、主に2セットの[追加] [削除] [チェック]などの動作動作から始まり、時間計算量と空間計算量、およびさまざまな状況での長所と短所を分析して、後で選択できるようにします。 。より良い選択へ。

1.増やす

配列リスト:

add(E e)
add(int index, E element)
addAll(Collection<? extends E> c)
addAll(int index, Collection<? extends E> c)

LinkedList:

addFirst(E e)
addLast(E e)
add(E e)
add(int index, E element)
addAll(Collection<? extends E> c)
addAll(int index, Collection<? extends E> c)

上記の2セットのApiの分析から、増加は主に数の増加と位置の増加という2つの次元によるものです。
数量:単一、複数の
位置:最初、最後、中間。
その2つの次元は6つの組み合わせで構成できます。単一の操作と複数の操作は同じであり、時間の複雑さに影響を与えないため、場所のみが分析されます。

背景を分析すると、両方とも現在n個の要素があります。

a。最初の位置に
ArrayListを追加する:使用されるメソッドはadd(int index、E element)です。最下層は配列構造であるため、要素が最初の位置に追加されると、後続のnビット要素は次のようになります。複雑さはO(n)です。この移動の時間消費に加えて、要素の追加に伴う容量が十分でない場合は、配列の拡張による消費も考慮する必要があります。

LinkedList:使用されるメソッドはaddFirst(E e)であり、元の最初の要素のリンクを解除して新しい要素ノードを追加する必要があるため、時間計算量はO(1)であり、コンテナーに従わない要素の数が増え、増加します。
実験

public static void main(String[] args)  {

// arrayList
    long s = System.currentTimeMillis();
    ArrayList arrayList = new ArrayList();
    for (int i = 0; i < 150000; i++) {
        arrayList.add(0,i);
    }
    long b = System.currentTimeMillis();
    System.out.println(b-s);
    
// linkedList
    LinkedList linkedList = new LinkedList();
    for (int i = 0; i < 150000; i++) {
        linkedList.add(0,i);
    }
    long c = System.currentTimeMillis();
    System.out.println(c-b);
}

結果:2298、6

这一轮PK结果: linkedList  优于 arrayList

b。最後に
ArrayListを追加する:使用されるメソッドはadd(E e)です。これは最後にのみ追加され、要素の移動を伴わないため、時間計算量はO(1)です。要素の追加を伴う場合、容量が足りない、アレイの拡張による消費を考慮する。

LinkedList:使用されるメソッドはaddLast(E e)で、最後に元の要素のリンクを解除し、新しい要素ノードを追加する必要があります。違いは、LInkedListがあるため、最後の要素を最初のインデックスから検索する必要がないことです。リンクリストの最初と最後へのポインタは内部的に維持されます。したがって、addFirst(E e)と同じであるため、時間計算量はO(1)です。

実験

 public static void main(String[] args)  {
 
    long s = System.currentTimeMillis();
    ArrayList arrayList = new ArrayList();
    for (int i = 0; i < 1500000; i++) {
        arrayList.add(i);
    }
    long b = System.currentTimeMillis();
    System.out.println(b-s);

    LinkedList linkedList = new LinkedList();
    for (int i = 0; i < 1500000; i++) {
        linkedList.add(i);
    }
    long c = System.currentTimeMillis();
    System.out.println(c-b);
}

結果:58、17

这一轮PK结果:    arrayList  略逊于  linkedList

c。中央に
ArrayListを追加:使用されるメソッドはadd(int index、E element)です。最下層は配列構造であるため、添え字を介して要素を取得する時間計算量はO(1)ですが、増加位置はしたがって、インデックス添え字の後のすべての要素(size-index)を後方に移動する必要があり、時間計算量はO(n)です。要素を追加するときに容量が十分でない場合は、配列を考慮する必要があります。消費。

LinkedList:使用されるメソッドはadd(int index、E element)です。最下層はリンクリスト構造であるため、添え字を介して要素を取得する時間計算量はO(n)であり、増加位置は中央にあります。最初と最後に追加された操作と同じです。、その時間計算量はO(1)です。

実験

public static void main(String[] args)  {

    long s = System.currentTimeMillis();
    ArrayList arrayList = new ArrayList();
    for (int i = 0; i < 150000; i++) {
        int index = 0;
        if (i>2){
            index = i/3;
        }
        arrayList.add(index,i);
    }
    long b = System.currentTimeMillis();
    System.out.println(b-s);

    LinkedList linkedList = new LinkedList();
    for (int i = 0; i < 150000; i++) {
        int index = 0;
        if (i>2){
            index = i/3;
        }
        linkedList.add(index,i);
    }
    long c = System.currentTimeMillis();
    System.out.println(c-b);
}

結果:1387、14626

这一轮PK结果:   
实验结果 arrayList 优于 linkedList  原因不详,还望高手指点。

行動を増やすため。最初の位置に頻繁に追加される場合は、LinkedListを検討してください。他の位置は、他の側面と組み合わせて検討できます。

2つの削除

コレクションとしては、2つを使用してデータを保存するため、追加と削除が不可欠です。どちらの場合も、削除関数は追加関数と同じです。オブジェクト指向の観点からは、追加と削除はどちらも操作動作です。操作は抽象クラスであり、追加と削除は操作の実装サブクラスです。

追加または削除の場合、操作の前の準備は位置を見つけることです。ArrayListとLinkedListの違いは、基礎となる構造が配列であり、そのインデックスの時間計算量がO(1)であるということです。アレイは位置を考慮する必要があります。アレイの移動と容量、およびリンクリストを考慮する必要はありません。もう1つはリンクリストで、インデックスの時間計算量はO(n)です。したがって、削除と追加の場合、動作の結果は一貫しています。削除について以下に簡単に説明します。

a。
先頭での削除先頭の削除の場合、インデックスの時間計算量はO(1)です。配列を削除した後、位置を移動する必要がありますが、リンクリストは移動しません。

b。
途中で削除する途中で削除する場合、インデックス時間の複雑さは途中で増加する場合と同じです。操作も一貫しており、再度説明することはありません。

c。最後に削除する最後に削除
する場合は、最後に追加することと一致します。時間計算量はすべてO(1)であり、操作は同じであるため、再度説明することはしません。

トリプルインデックス

インデックス作成に関連する2つの方法は次のとおりです。

	get(int index)
	indexOf(Object o)
	contains(Object o)

arrayListのget(int index)メソッドは、その最下層が配列構造であるため、添え字を介して要素を取得する時間計算量はO(1)ですが、他のノードインデックスの先頭と末尾を除くLinkedListの時間計算量はO(n)、

indexOf(Object o)は、要素の比較を通じて添え字を取得するためのものであり、内部でトラバースする必要があり、時間計算量はO(n)です。

contains(Object o)メソッドは、要素を比較する必要があるため、実際には内部でIndexOf()メソッドを呼び出すため、時間計算量はO(n)です。

結論として

要約すると、2つの違いは主にその内部構造にあり、1つは配列で、もう1つはリンクリストです。配列とリンクリストの最大の違いは、そのインデックスによって引き起こされる時間の複雑さです。もう1つは、配列の追加および削除操作で要素の移動を考慮する必要があることです。
操作要素の追加と削除の頻度が高くなく、要素のクエリと取得の頻度が高い場合は、arrayListを検討できます。

操作要素の追加と削除の頻度が高く、要素のクエリと取得の要件が高くない
場合は、操作位置aを分析します操作のメイン位置が先頭にある場合は、linkedListの使用を検討してください
。操作の主な位置は中央の位置にあり、ArrayList bを検討できます
。操作の主な位置が最後にある場合、LinkedListとarrayListの間に大きな違いはなく、特定の選択は他の追加に焦点を当てることができます。機能

おすすめ

転載: blog.csdn.net/weixin_43901067/article/details/105052559