Java ArayListはどうしてRandom Accessインターフェースを実現しますか?
6215 ワード
私たちの開発では、Listインターフェースは最も一般的ですが、毎日のようにArayListやLinkdListを使っています。しかし、慎重な学生はRandomAccessインターフェースを実現しています。Linked ListはRandom Accessインターフェースを実現していません。これは何ですか?
RandomAccessは、Listがこのインターフェースを実現すれば、高速ランダムアクセスがサポートされるというマークインターフェースです。ランダムアクセスとは何ですか?次に例を挙げて説明します。Collectionは集合の道具類です。Collectionのソースコードの中の2つの検索方法を見てみます。
したがって、我々のアプリケーションでは、Listインターフェースを使用するどのような実装クラスを考慮すると、より効率的にシーンニーズを満たすことができます。そこでここではRandomAccessインターフェースを実現することによって、Listのどの実現クラスを区別しますか?
締め括りをつける
*最後の要約文:RandomAccessインターフェースを実現するListは、forループを通じてデータを巡回することができ、iteratorエルゴードデータを使用するよりも効率的に、RandomAccessインターフェースを実現していないListは、iteratorエルゴードデータを経由してforループを使用するよりもデータを遍歴することができます。
public class ArrayList extends AbstractList
implements List, RandomAccess, Cloneable, java.io.Serializable
public class LinkedList
extends AbstractSequentialList
implements List, Deque, Cloneable, java.io.Serializable
RandomAccessインターフェースの中では空いていますが、RandomAccessインターフェースは何ですか?public interface RandomAccess {
}
Random AccessインターフェースRandomAccessは、Listがこのインターフェースを実現すれば、高速ランダムアクセスがサポートされるというマークインターフェースです。ランダムアクセスとは何ですか?次に例を挙げて説明します。Collectionは集合の道具類です。Collectionのソースコードの中の2つの検索方法を見てみます。
public static
int binarySearch(List extends Comparable super T>> list, T key) {
if (list instanceof RandomAccess || list.size()
ソースでは、listがRandomAccessの例かどうかを判断することができますが、もしそうであれば、indexedvinarySearchの方法を実行します。そうでなければ、iteratoBinarySearchの方法を実行します。この二つの方法を見てみます。private static
int indexedBinarySearch(List extends Comparable super T>> list, T key) {
int low = 0;
int high = list.size()-1;
while (low <= high) {
int mid = (low + high) >>> 1;
Comparable super T> midVal = list.get(mid);
int cmp = midVal.compareTo(key);
if (cmp < 0)
low = mid + 1;
else if (cmp > 0)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found
}
private static
int iteratorBinarySearch(List extends Comparable super T>> list, T key)
{
int low = 0;
int high = list.size()-1;
ListIterator extends Comparable super T>> i = list.listIterator();
while (low <= high) {
int mid = (low + high) >>> 1;
Comparable super T> midVal = get(i, mid);
int cmp = midVal.compareTo(key);
if (cmp < 0)
low = mid + 1;
else if (cmp > 0)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found
}
上記の2つの方法のソースコードは、RandomAccessインターフェースのListはインデックスを使用して遍歴していますが、RandomAccessインターフェースを実現していないListは、ローズマリーを使用して遍歴しています。なぜこのように設計しますか?二分検索のエルゴード操作に関わる以上、ArayListとLinked Listエルゴードの性能を分析してみましょう。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 arrayList = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
arrayList.add(i);
}
//
long startTime = System.currentTimeMillis();
for (int i = 0; i < arrayList.size(); i++) {
arrayList.get(i);
}
//
long endTime = System.currentTimeMillis();
//
long resultTime = endTime - startTime;
return resultTime;
}
// ArrayList iterator
public static long arrayListIterator() {
List arrayList = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
arrayList.add(i);
}
//
long startTime = System.currentTimeMillis();
Iterator 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 linkedList = new LinkedList<>();
for (int i = 0; i < 10000; i++) {
linkedList.add(i);
}
//
long startTime = System.currentTimeMillis();
for (int i = 0; i < linkedList.size(); i++) {
linkedList.get(i);
}
//
long endTime = System.currentTimeMillis();
//
long resultTime = endTime - startTime;
return resultTime;
}
// LinkedList iterator
public static long linkedListIterator() {
List linkedList = new LinkedList<>();
for (int i = 0; i < 10000; i++) {
linkedList.add(i);
}
//
long startTime = System.currentTimeMillis();
Iterator 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エルゴードを通過するのはiteratorを通過するより少し早いです。Linked Listはiteratorを通過するのがforエルゴードより速いです。したがって、我々のアプリケーションでは、Listインターフェースを使用するどのような実装クラスを考慮すると、より効率的にシーンニーズを満たすことができます。そこでここではRandomAccessインターフェースを実現することによって、Listのどの実現クラスを区別しますか?
締め括りをつける
*最後の要約文:RandomAccessインターフェースを実現するListは、forループを通じてデータを巡回することができ、iteratorエルゴードデータを使用するよりも効率的に、RandomAccessインターフェースを実現していないListは、iteratorエルゴードデータを経由してforループを使用するよりもデータを遍歴することができます。