Существует ли различие в производительности между для цикла и цикла foreach?

175
задан Martin Vseticka 25 June 2017 в 17:48
поделиться

8 ответов

От Объекта 46 в Эффективный Java Joshua Bloch:

цикл foreach, представленный в выпуске 1.5, избавляется от помехи и возможности для ошибки путем сокрытия итератора или индексной переменной полностью. Получающаяся идиома применяется одинаково к наборам и массивам:

// The preferred idiom for iterating over collections and arrays
for (Element e : elements) {
    doSomething(e);
}

, Когда Вы видите двоеточие (:), считайте его как “in. ” Таким образом, цикл выше чтений как “for каждый элемент e в элементах. Примечание ”, что нет никакой потери производительности для использования цикла foreach, даже для массивов. На самом деле это может предложить небольшое преимущество производительности перед дежурным блюдом для цикла при некоторых обстоятельствах, поскольку это вычисляет предел индекса массива только однажды. В то время как можно сделать это вручную (Объект 45), программисты don’t всегда делают так.

201
ответ дан Vijay Dev 23 November 2019 в 20:27
поделиться

Единственный способ знать наверняка состоит в том, чтобы сравнить его, и даже который является не столь прост, как это может звучать . JIT-компилятор может сделать очень неожиданные вещи к Вашему коду.

3
ответ дан Jouni K. Seppänen 23 November 2019 в 20:27
поделиться

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

Каждый раз, когда я вижу индексируемый цикл, я должен проанализировать его немного дольше, чтобы удостовериться, что он делает то, что я думаю , он делает, Например, он начинает с нуля, он включает или исключает конечную точку и т.д.?

Большую часть моего времени, кажется, потрачен, читая код (что я записал, или кто-то еще записал), и ясность почти всегда более важна, чем производительность. Его легкое для отклонения производительности в эти дни, потому что Горячая точка делает такое удивительное задание.

4
ответ дан Fortyrunner 23 November 2019 в 20:27
поделиться

Всегда лучше использовать итератор вместо индексации. Это вызвано тем, что итератор является наиболее вероятным optimzied для Реализации списка, в то время как индексировано (вызов добираются), не мог бы быть. Например, LinkedList является Список, но индексирующий через его элементы будет медленнее, чем итерация использования итератора.

4
ответ дан Steve Kuo 23 November 2019 в 20:27
поделиться

Ну, влияние производительности главным образом незначительно, но не является нулем. Если Вы смотрите на JavaDoc RandomAccess интерфейс:

Как показывает опыт, Реализация списка должна реализовать этот интерфейс если, для типичных экземпляров класса, этого цикла:

for (int i=0, n=list.size(); i < n; i++)
    list.get(i);

выполнения быстрее, чем этот цикл:

for (Iterator i=list.iterator(); i.hasNext();)
      i.next();

И цикл foreach использует версию с итератором, таким образом, для ArrayList, например, цикл foreach не является самым быстрым.

11
ответ дан Lii 23 November 2019 в 20:27
поделиться

Цикл foreach должен обычно предпочитаться. "Получить" подход может быть медленнее, если Реализация списка, которую Вы используете, не поддерживает произвольный доступ. Например, если бы LinkedList используется, Вы понесли бы пересекающиеся расходы, тогда как для - каждый подход использует итератор, который отслеживает его положение в списке. Больше информации о нюансы цикла foreach .

, я думаю статья, теперь здесь: новое местоположение

ссылка, показанная здесь, была мертва.

13
ответ дан ncmathsadist 23 November 2019 в 20:27
поделиться

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

Первый, классический способ цикличного выполнения через Список:

for(int i=0;i<strings.size();i++) { /* do something using strings.get(i) */ }
118-секундный, предпочтительный путь, так как это менее подвержено ошибкам (сколько раз ВЫ сделали "ой, смешали переменные i и j в этих циклах в циклах" вещь?).

for(String s : strings) { /* do something using s */ }

В-третьих, микрооптимизированный для цикла:

int size = strings.size();
for(int i=0;++i<=size;) { /* do something using strings.get(i) */ }

Теперь фактические два цента: По крайней мере, то, когда я тестировал их, третий был самым быстрым при подсчете миллисекунд на то, сколько времени он взял для каждого типа цикла с простой операцией в нем, повторилось несколько миллионов раз - это использовало Java 5 с jre1.6u10 в Windows в случае, если любому интересно.

, В то время как это, по крайней мере, кажется, так, чтобы третий был самым быстрым, действительно необходимо спросить себя, если Вы хотите рискнуть реализации этой локальной оптимизации везде в Вашем коде цикличного выполнения с тех пор от того, что я видел, фактическое цикличное выполнение обычно не является самой трудоемкой частью никакой реальной программы (или возможно я просто работаю над неправильным полем, кто знает). И также как я упомянул в предлоге для цикла foreach Java (некоторые называют его цикл Итератора и другие как для - в цикле ), Вы, менее вероятно, поразите тот особая глупая ошибка при использовании его. И прежде, чем дебатировать, как это даже может даже быть быстрее, чем другие, помните, что javac не оптимизирует байт-код вообще (хорошо, почти вообще так или иначе), это просто компилирует его.

, Если Вы в микрооптимизацию, хотя и/или Ваше программное обеспечение использует много рекурсивных циклов и такого тогда, можно интересоваться третьим типом цикла. Просто не забудьте сравнивать своего программного обеспечения хорошо и прежде и после изменения для циклов, которые Вы имеете к этому нечетному, микрооптимизировал тот.

28
ответ дан MrSmith42 23 November 2019 в 20:27
поделиться

Даже с чем-то как ArrayList или Вектор, где "добираются", поиск простого массива, второй цикл все еще имеет дополнительные издержки, которые не делает первый. Я ожидал бы, что он будет крошечным битом медленнее, чем первое.

3
ответ дан Paul Tomblin 23 November 2019 в 20:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: