Есть ли разница в производительности между циклом for и циклом for-each? - PullRequest
169 голосов
/ 02 ноября 2008

Какова разница в производительности между следующими двумя циклами, если таковая имеется?

for (Object o: objectArrayList) {
    o.DoSomething();
}

и

for (int i=0; i<objectArrayList.size(); i++) {
    objectArrayList.get(i).DoSomething();
}

Ответы [ 17 ]

3 голосов
/ 02 ноября 2008

Даже с чем-то вроде ArrayList или Vector, где «get» - это простой поиск в массиве, у второго цикла все еще есть дополнительные издержки, которых нет у первого. Я ожидаю, что это будет немного медленнее, чем первый.

2 голосов
/ 06 ноября 2013

По имени переменной objectArrayList я предполагаю, что это экземпляр java.util.ArrayList. В этом случае разница в производительности была бы незаметной.

С другой стороны, если это экземпляр java.util.LinkedList, второй подход будет намного медленнее, поскольку List#get(int) является операцией O (n).

Таким образом, первый подход всегда предпочтителен, если только индекс не нужен логике в цикле.

1 голос
/ 21 августа 2017

Принятый ответ отвечает на вопрос, кроме исключительного случая ArrayList ...

Так как большинство разработчиков полагаются на ArrayList (по крайней мере, я так считаю)

Так что я обязан добавить правильный ответ здесь.

Прямо из документации разработчика: -

Улучшенный цикл for (также известный как цикл for-each) можно использовать для коллекций, которые реализуют интерфейс Iterable, и для массивов. В коллекциях выделяется итератор для выполнения интерфейсных вызовов hasNext () и next (). С ArrayList рукописный подсчитанный цикл примерно в 3 раза быстрее (с JIT или без него), но для других коллекций расширенный синтаксис цикла for будет в точности эквивалентен явному использованию итератора.

Существует несколько альтернатив для перебора массива:

static class Foo {
    int mSplat;
}

Foo[] mArray = ...

public void zero() {
    int sum = 0;
    for (int i = 0; i < mArray.length; ++i) {
        sum += mArray[i].mSplat;
    }
}

public void one() {
    int sum = 0;
    Foo[] localArray = mArray;
    int len = localArray.length;

    for (int i = 0; i < len; ++i) {
        sum += localArray[i].mSplat;
    }
}

public void two() {
    int sum = 0;
    for (Foo a : mArray) {
        sum += a.mSplat;
    }
}

zero () самый медленный, потому что JIT еще не может оптимизировать стоимость получения длины массива один раз для каждой итерации цикла.

one () быстрее. Он вытягивает все в локальные переменные, избегая поиска. Только длина массива обеспечивает выигрыш в производительности.

two () является самым быстрым для устройств без JIT и неотличимым от one () для устройств с JIT. Он использует расширенный синтаксис цикла for, представленный в версии 1.5 языка программирования Java.

Итак, по умолчанию вы должны использовать расширенный цикл for, но рассмотрите рукописный счетный цикл для критической итерации ArrayList.

1 голос
/ 14 июня 2017

Странно, что никто не упомянул очевидное - foreach выделяет память (в форме итератора), тогда как нормальный цикл for не выделяет никакой памяти. Для игр на Android это проблема, потому что это означает, что сборщик мусора будет запускаться периодически. В игре вы не хотите, чтобы сборщик мусора работал ... КОГДА-ЛИБО. Поэтому не используйте циклы foreach в своем методе рисования (или рендеринга).

1 голос
/ 22 января 2016
1. for(Object o: objectArrayList){
    o.DoSomthing();
}
and

2. for(int i=0; i<objectArrayList.size(); i++){
    objectArrayList.get(i).DoSomthing();
}

И то, и другое делает то же самое, но для простого и безопасного программирования для каждого существует возможность возникновения ошибок при втором способе использования.

0 голосов
/ 05 апреля 2019
public class FirstJavaProgram {

    public static void main(String[] args) 
    {
        int a[]={1,2,3,45,6,6};

// Method 1: this is simple way to print array 

        for(int i=0;i<a.length;i++) 
        { 
            System.out.print(a[i]+" ");
        }

// Method 2: Enhanced For loop

        for(int i:a)
        {
            System.out.print(i+" ");
        }
    }
}
0 голосов
/ 01 марта 2018

Да, вариант for-each быстрее, чем обычно index-based-for-loop.

for-each вариант использует iterator. Таким образом, обход происходит быстрее, чем обычно for цикл, основанный на индексах.
Это потому, что iterator оптимизированы для обхода, потому что он указывает на непосредственно перед следующим элементом и сразу после предыдущего элемента . Одна из причин того, что index-based-for-loop является медленным, заключается в том, что он должен вычислять и перемещаться в положение элемента каждый раз , что не соответствует iterator.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...