リストの本来の姿では、全要素を順番に操作するには、Iteratorパターンを使う。
しかし、RandomAccessインターフェースを実装しているコレクションでは、インデックスで直接指定する方が速い。
と言ってもそんなに大差ないけどね。
ということで、比較してみた。以下は簡単なサンプル
ArrayListは、RandomAccessインターフェースを実装しているので、インデックスで直接指定する方が速いはず。
public static void main(String[] args) { ArrayList<String> list = new ArrayList<String>(); for (int i=0; i<1000000; i++) { list.add("Hello world"); } // ① Iterator long listStart = java.lang.System.nanoTime(); for (Iterator<String> it = list.iterator(); it.hasNext();) { it.next().toString(); } long listEnd = java.lang.System.nanoTime(); System.out.println("Iterator : " + (listEnd - listStart)); // ② for each long listStart1 = java.lang.System.nanoTime(); for (String str : list) { str.toString(); } long listEnd1 = java.lang.System.nanoTime(); System.out.println("foreach : " + (listEnd1 - listStart1)); // ③ インデックス long listStart2 = java.lang.System.nanoTime(); int size = list.size(); for (int i = 0; i < size; i++) { list.get(i).toString(); } long listEnd2 = java.lang.System.nanoTime(); System.out.println("size : " + (listEnd2 - listStart2)); }
結果はこんな感じ。
① Iterator : 39518710
② foreach : 35311750
③ size : 12804141
そんなに大きな差ではないけど、やっぱりインデックスで直接指定する方が早いみたい。
ちなみにLinkedListだとこうなる。
public static void main(String[] args) { LinkedList<String> list = new LinkedList<String>(); for (int i=0; i<1000000; i++) { list.add("Hello world"); } // ① Iterator long listStart = java.lang.System.nanoTime(); for (Iterator<String> it = list.iterator(); it.hasNext();) { it.next().toString(); } long listEnd = java.lang.System.nanoTime(); System.out.println("Iterator : " + (listEnd - listStart)); // ② for each long listStart1 = java.lang.System.nanoTime(); for (String str : list) { str.toString(); } long listEnd1 = java.lang.System.nanoTime(); System.out.println("foreach : " + (listEnd1 - listStart1)); }
結果はこんな感じ。
① Iterator : 23345984
② foreach : 22090517
LinkedListの場合は、インデックスを使わなければ、まぁどちらでもいいということか。
(LinkedListでインデックスを使い要素を取り出すのは問題外なので書いてません)
結論
1.基本的にはリストIteratorパターンを使う
2.ArrayListでどうしてもパフォーマンスがきになる場合はインデックスを使う
3.LinkedListはIteratorパターンしか使わない
基本的にはIteratorパターン使おうねってことで。
まめ
LinkedListでインデックスを使い要素を取り出すのはやめておきましょう。
あまりにも遅すぎます。
インデックスで繰り返すときに size を for分の中で取得する人がいますが、
上記サンプルのように for文の外で取得しましょう。
× for (int i = 0; i < list.size(); i++) ○ int size = list.size(); for (int i = 0; i < size; i++) ※RandomAccessインターフェース Iteratorを使って先頭から順番にアクセスする(順次アクセス)よりも、 インデックスを使って途中の要素を直接指定する(ランダムアクセス)の方が 高速ということを意味する。(想定される) (RandomAccessを実装していないリストは、LinkedList)