1. 程式人生 > >JAVA集合:for迴圈、foreach、迭代器效率比較

JAVA集合:for迴圈、foreach、迭代器效率比較

前言

寫程式碼的過程中,經常需要遍歷集合,選擇一個高效的遍歷方法非常重要,今天來看下for迴圈、foreach、迭代器效率比較,主要從ArrayList和LinkedList來分析。
直接上程式碼測試

ArrayList


        List<Integer> integers = Lists.newArrayList();
        for(int i=0;i<100000;i++){
            integers.add(i);
        }

        long start1 = System.currentTimeMillis();
        for(int count =0 ;count<10;count++){
            for(int i=0;i<integers.size();i++){
                int j=integers.get(i);
            }
        }
        System.out.println(String.format("for迴圈100次時間:%s ms",System.currentTimeMillis()-start1));

        long start2 = System.currentTimeMillis();
        for(int count =0 ;count<10;count++) {
            for (Integer i : integers) {
               int j = i;
            }
        }
        System.out.println(String.format("foreach迴圈100次時間:%s ms",System.currentTimeMillis()-start2));

        long start3 = System.currentTimeMillis();
        for(int count =0 ;count<10;count++) {
            Iterator<Integer> iterator = integers.iterator();
            while(iterator.hasNext()){
                int j=iterator.next();
            }
        }
        System.out.println(String.format("迭代器迴圈100次時間:%s ms",System.currentTimeMillis()-start3));

結果:

for迴圈100次時間:15 ms
foreach迴圈100次時間:25 ms
迭代器迴圈100次時間:20 ms

ArrayList下三者效率差不多,for迴圈最優,因為ArrayList通過陣列來實現,陣列通過索引來定位的時間複雜度是O(1),1次就能定位到,所以效率非常高

LinkedList

List<Integer> integers = Lists.newLinkedList();
        for(int i=0;i<100000;i++){
            integers.add(i);
        }

        long start1 = System.currentTimeMillis();
        for(int count =0 ;count<10;count++){
            for(int i=0;i<integers.size();i++){
                int j=integers.get(i);
            }
        }
        System.out.println(String.format("for迴圈100次時間:%s ms",System.currentTimeMillis()-start1));

        long start2 = System.currentTimeMillis();
        for(int count =0 ;count<10;count++) {
            for (Integer i : integers) {
               int j = i;
            }
        }
        System.out.println(String.format("foreach迴圈100次時間:%s ms",System.currentTimeMillis()-start2));

        long start3 = System.currentTimeMillis();
        for(int count =0 ;count<10;count++) {
            Iterator<Integer> iterator = integers.iterator();
            while(iterator.hasNext()){
                int j=iterator.next();
            }
        }
        System.out.println(String.format("迭代器迴圈100次時間:%s ms",System.currentTimeMillis()-start3));

結果:

for迴圈100次時間:59729 ms
foreach迴圈100次時間:18 ms
迭代器迴圈100次時間:14 ms

可以看到for迴圈在LinkedList下效率特別低,我們來看下LinkedList的get做了什麼

 Node<E> node(int index) {
        // assert isElementIndex(index);

        if (index < (size >> 1)) {
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

get呼叫到node(index)方法,從程式碼可以看到,當index<size/2時從前往後找,否則從後往前找,使LinkedList的每個元素通過下標方式查詢最多查詢size/2次,因此遍歷100000個元素總共需要查詢的次數是size/2/2size = 100000100000/4,效率遠低於ArrayList通過下標直接定位,總共只需要查詢100000次,所以經常會說LinkedList的查詢效率低,ArrayList的查詢效率高,其實這裡指的是for迴圈通過下標查詢的角度,通過迭代器查詢的效率都很高,差不多。