Эффективность 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. См. Также этот ответ, в котором обсуждается предмет.
Ответы
Ответ 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 нет даже штрафа за производительность, даже для массивов. Фактически, он может предложить небольшое преимущество в производительности по сравнению с обычным циклом в некоторых случаях, поскольку он вычисляет предел индекса массива только один раз. Подробнее см. В .