Подтвердить что ты не робот

Эффективность Java-цикла ( "для" и "foreach" )

(Вопрос для тех, кто хорошо знает компиляцию и оптимизацию JVM...: -)

Есть ли какие-либо из шаблонов "for" и "foreach", явно превосходящие другие?

Рассмотрим следующие два примера:

public void forLoop(String[] text)
{
    if (text != null)
    {
        for (int i=0; i<text.length; i++)
        {
            // Do something with text[i]
        }
    }
}

public void foreachLoop(String[] text)
{
    if (text != null)
    {
        for (String s : text)
        {
            // Do something with s, exactly as with text[i]
        }
    }
}

Является forLoop быстрее или медленнее, чем foreachLoop?

Предполагая, что в обоих случаях массив text не нуждался в каких-либо проверках здравомыслия, есть ли явный победитель или еще слишком близко, чтобы позвонить?

РЕДАКТ. Как отмечалось в некоторых ответах, производительность должна быть одинаковой для массивов, тогда как шаблон "foreach" может быть немного лучше для абстрактных типов данных, таких как List. См. Также этот ответ, в котором обсуждается предмет.

4b9b3361

Ответ 1

Из раздел 14.14.2 JLS:

В противном случае выражение обязательно имеет тип массива, T []. Пусть L1... Lm - (возможно, пустая) последовательность меток, непосредственно предшествующая расширению для оператора. Тогда значение расширенного оператора for задается следующим базовым для оператора:

T[] a = Expression;
L1: L2: ... Lm:
for (int i = 0; i < a.length; i++) {
        VariableModifiersopt Type Identifier = a[i];
        Statement
}

Другими словами, я ожидаю, что они будут скомпилированы в один и тот же код.

Там определенно явный победитель: улучшенный цикл for более читабельен. Это должно быть вашей главной заботой - вы должны даже учитывать микро-оптимизацию такого рода вещей, когда вы доказали, что наиболее читаемая форма не работает так хорошо, как вы хотите.

Ответ 2

Вы можете написать свой собственный простой тест, который измеряет время выполнения.

long start = System.currentTimeMillis();
forLoop(text);
long end = System.currentTimeMillis();
long result = end - start;

результатом является время выполнения.

Ответ 3

Вы должны выбрать вариант, который читается почти каждый раз, если вы не знаете, что у вас проблема с производительностью.

В этом случае я бы сказал, что они гарантированно будут одинаковыми.

Единственное различие заключается в дополнительной проверке на text.length, которая скорее всего будет медленнее, чем быстрее.

Я также гарантирую, что текст никогда не будет статическим. например используя аннотацию @NotNull. Лучше поймать эти проблемы во время компиляции/сборки (и это будет быстрее)

Ответ 4

Поскольку вы используете тип array, разница в производительности не имеет значения. В итоге они получат такую ​​же производительность после прохождения воронки optimization.

Но если вы используете ADT, например List, то forEachLoop, по-видимому, лучший выбор по сравнению с несколькими вызовами get(i).

Ответ 5

Для использования цикла for-each нет даже штрафа за производительность, даже для массивов. Фактически, он может предложить небольшое преимущество в производительности по сравнению с обычным циклом в некоторых случаях, поскольку он вычисляет предел индекса массива только один раз. Подробнее см. В .