Java ArrayListがRandomAccessインターフェースを実装するのはなぜですか?

概要:
ArrayListのトラバーサルスルーforは、イテレーターのトラバーサルよりもわずかに高速です。LinkedListのイテレータートラバーサルは、トラバーサルスルーforよりも高速です。

したがって、このアプリケーションでは、実際のシーンのニーズをより適切に満たすことができる、使用するListインターフェイスの実装クラスを検討する必要があります。したがって、ここでは、RandomAccessインターフェイスを実装して、Listの実装クラスを区別します。

私たちの開発では、Listインターフェースが最も一般的で、ほぼ毎日ArrayListまたはLinkedListを使用していますが、注意深い学生にRandomAccessインターフェースがArrayListに実装されているのに、LinkedListがRandomAccessインターフェースを実装していないことを知ってもらいます。なぜですか。 ?

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable

   
    
    

RandomAccessインターフェースは空です。RandomAccessインターフェースとは何ですか?

public interface RandomAccess {
}

   
    
    
RandomAccessインターフェース

RandomAccessはマーカーインターフェイスです。公式の説明では、Listがこのインターフェイスを実装している限り、高速ランダムアクセスをサポートできます。そして、ランダムアクセスとは何ですか?例を見てみましょう。
コレクションはコレクションのツールクラスです。コレクションソースコードのバイナリ検索メソッドを見てみましょう。

public static <T>
    int binarySearch(List<? extends Comparable<? super T>> list, T key) {
        if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
            return Collections.indexedBinarySearch(list, key);
        else
            return Collections.iteratorBinarySearch(list, key);
    }

   
    
    

ソースコードからわかるように、リストがRandomAccessのインスタンスであるかどうかが判断され、インスタンスである場合はindexedBinarySearchメソッドが実行され、そうでない場合はiteratorBinarySearchメソッドが実行されます。次に、これら2つの方法を見てみましょう。

private static <T>
int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {
    int low = 0;
    int high = list.size()-1;
while (low &lt;= high) {
    int mid = (low + high) &gt;&gt;&gt; 1;
    Comparable&lt;? super T&gt; midVal = list.get(mid);
    int cmp = midVal.compareTo(key);

    if (cmp &lt; 0)
        low = mid + 1;
    else if (cmp &gt; 0)
        high = mid - 1;
    else
        return mid; // key found
}
return -(low + 1);  // key not found

}
private static <T>
int iteratorBinarySearch(List <?extends Comparable <?super T >> list、T key)
{ int low = 0; int high = list.size()-1; ListIterator <?Comparable <?スーパーT >> i = list.listIterator();


while (low &lt;= high) {
    int mid = (low + high) &gt;&gt;&gt; 1;
    Comparable&lt;? super T&gt; midVal = get(i, mid);
    int cmp = midVal.compareTo(key);

    if (cmp &lt; 0)
        low = mid + 1;
    else if (cmp &gt; 0)
        high = mid - 1;
    else
        return mid; // key found
}
return -(low + 1);  // key not found

}

上記の2つのメソッドのソースコードは、RandomAccessインターフェイスを実装するリストがインデックストラバーサルを使用するのに対し、RandomAccessインターフェイスを実装しないリストはイテレータトラバーサルを使用することを示しています。では、なぜこのように設計されているのでしょうか。
二分探索のトラバーサル操作が含まれているので、次にArrayListおよびLinkedListトラバーシング要素のパフォーマンスを分析しましょう。

public class CollectionTest {
    public static void main(String[] args){
        long arrayListIndexedTime = arrayListIndexed();
        long arrayListIteratorTime = arrayListIterator();
        long linkedListIndexedTime = linkedListIndexed();
        long linkedListIteratorTime = linkedListIterator();
        System.out.println("测试ArrayList通过for遍历所消耗时间:" + arrayListIndexedTime);
        System.out.println("测试ArrayList通过iterator遍历所消耗时间:" + arrayListIteratorTime);
        System.out.println("测试LinkedList通过for遍历所消耗时间:" + linkedListIndexedTime);
        System.out.println("测试LinkedList通过iterator遍历所消耗时间:" + linkedListIteratorTime);
    }
//测试ArrayList通过for遍历所消耗时间
public static long arrayListIndexed() {
    List&lt;Integer&gt; arrayList = new ArrayList&lt;&gt;();
    for (int i = 0; i &lt; 10000; i++) {
        arrayList.add(i);
    }
    //记录开始时间
    long startTime = System.currentTimeMillis();
    for (int i = 0; i &lt; arrayList.size(); i++) {
        arrayList.get(i);
    }
    //记录结束时间
    long endTime = System.currentTimeMillis();
    //遍历消耗时间
    long resultTime = endTime - startTime;
    return resultTime;
}

//测试ArrayList通过iterator遍历所消耗时间
public static long arrayListIterator() {
    List&lt;Integer&gt; arrayList = new ArrayList&lt;&gt;();
    for (int i = 0; i &lt; 10000; i++) {
        arrayList.add(i);
    }
    //记录开始时间
    long startTime = System.currentTimeMillis();
    Iterator&lt;Integer&gt; iterator = arrayList.iterator();
    while (iterator.hasNext()) {
        iterator.next();
    }
    //记录结束时间
    long endTime = System.currentTimeMillis();
    //遍历消耗时间
    long resultTime = endTime - startTime;
    return resultTime;
}

//测试LinkedList通过for遍历所消耗时间
public static long linkedListIndexed() {
    List&lt;Integer&gt; linkedList = new LinkedList&lt;&gt;();
    for (int i = 0; i &lt; 10000; i++) {
        linkedList.add(i);
    }
    //记录开始时间
    long startTime = System.currentTimeMillis();
    for (int i = 0; i &lt; linkedList.size(); i++) {
        linkedList.get(i);
    }
    //记录结束时间
    long endTime = System.currentTimeMillis();
    //遍历消耗时间
    long resultTime = endTime - startTime;
    return resultTime;
}

//测试LinkedList通过iterator遍历所消耗时间
public static long linkedListIterator() {
    List&lt;Integer&gt; linkedList = new LinkedList&lt;&gt;();
    for (int i = 0; i &lt; 10000; i++) {
        linkedList.add(i);
    }
    //记录开始时间
    long startTime = System.currentTimeMillis();
    Iterator&lt;Integer&gt; iterator = linkedList.iterator();
    while (iterator.hasNext()) {
        iterator.next();
    }
    //记录结束时间
    long endTime = System.currentTimeMillis();
    //遍历消耗时间
    long resultTime = endTime - startTime;
    return resultTime;
}

}

試験結果は以下のとおりです。

测试ArrayList通过for遍历所消耗时间:1
测试ArrayList通过iterator遍历所消耗时间:2
测试LinkedList通过for遍历所消耗时间:47
测试LinkedList通过iterator遍历所消耗时间:1

 
  
  

テスト結果を分析してみましょう。ArrayListトラバーサルスルーforは、イテレーターを介したトラバーサルよりもわずかに高速であり、LinkedListトラバーサルスルーforは、トラバーサルスルーforよりも高速です。

したがって、このアプリケーションでは、実際のシーンのニーズをより適切に満たすことができる、使用するListインターフェイスの実装クラスを検討する必要があります。したがって、ここでは、RandomAccessインターフェイスを実装して、Listの実装クラスを区別します。

総括する

**
最後に要約文:RandomAccessインターフェイスを実装するリストは、イテレータを使用してデータをトラバースするよりも効率的にforループを介してデータをトラバースできます。RandomAccessインターフェイスを実装しないリストは、forループを使用するよりも効率的にイテレータを介してデータをトラバースできます。データをトラバースします。
****

                                </div><div><div></div></div>
            <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-ff98e99283.css" rel="stylesheet">
                            </div>

私たちの開発では、Listインターフェースが最も一般的で、ほぼ毎日ArrayListまたはLinkedListを使用していますが、注意深い学生にRandomAccessインターフェースがArrayListに実装されているのに、LinkedListがRandomAccessインターフェースを実装していないことを知ってもらいます。なぜですか。 ?

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable

   
  
  

RandomAccessインターフェースは空です。RandomAccessインターフェースとは何ですか?

public interface RandomAccess {
}

   
  
  
RandomAccessインターフェース

RandomAccessはマーカーインターフェイスです。公式の説明では、Listがこのインターフェイスを実装している限り、高速ランダムアクセスをサポートできます。そして、ランダムアクセスとは何ですか?例を見てみましょう。
コレクションはコレクションのツールクラスです。コレクションソースコードのバイナリ検索メソッドを見てみましょう。

public static <T>
    int binarySearch(List<? extends Comparable<? super T>> list, T key) {
        if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
            return Collections.indexedBinarySearch(list, key);
        else
            return Collections.iteratorBinarySearch(list, key);
    }

   
  
  

ソースコードからわかるように、リストがRandomAccessのインスタンスであるかどうかが判断され、インスタンスである場合はindexedBinarySearchメソッドが実行され、そうでない場合はiteratorBinarySearchメソッドが実行されます。次に、これら2つの方法を見てみましょう。

private static <T>
int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {
    int low = 0;
    int high = list.size()-1;
while (low &lt;= high) {
    int mid = (low + high) &gt;&gt;&gt; 1;
    Comparable&lt;? super T&gt; midVal = list.get(mid);
    int cmp = midVal.compareTo(key);

    if (cmp &lt; 0)
        low = mid + 1;
    else if (cmp &gt; 0)
        high = mid - 1;
    else
        return mid; // key found
}
return -(low + 1);  // key not found

おすすめ

転載: blog.csdn.net/My_Way666/article/details/108279845