Вопрос-ответ

Is there a performance difference between a for loop and a for-each loop?

Есть ли разница в производительности между циклом for и циклом for-each?

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

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

и

for (int i=0; i<objectArrayList.size(); i++) {
objectArrayList.get(i).DoSomething();
}
Переведено автоматически
Ответ 1

Из пункта 46 книги Джошуа Блоха " Эффективная Java" :


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


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

Когда вы видите двоеточие (:), считайте его как
“в”. Таким образом, приведенный выше цикл читается как
“для каждого элемента e в elements”. Обратите внимание
что нет снижения производительности
при использовании цикла for-each даже для
массивов. Фактически, это может предложить небольшое
преимущество в производительности по сравнению с обычным циклом
при некоторых обстоятельствах цикл for, поскольку он
вычисляет предел индекса массива
только один раз. А сделать это можно
силы (пункт 45), программисты не
всегда так делаю.


Ответ 2

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

Во -первых, классический способ перебора списка:

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

Во-вторых, предпочтительный способ, поскольку он менее подвержен ошибкам (сколько раз ВЫ делали "ой, перепутали переменные i и j в этих циклах внутри циклов"?).

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

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

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

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

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

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

Ответ 3

Что ж, влияние на производительность в основном незначительно, но не равно нулю. Если вы посмотрите на JavaDoc из RandomAccess интерфейса:


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


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

работает быстрее, чем этот цикл:


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

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

Ответ 4

Обычно следует отдавать предпочтение циклу for-each. Подход "get" может быть медленнее, если используемая вами реализация списка не поддерживает произвольный доступ. Например, если используется LinkedList , вы понесете затраты на обход, тогда как подход for-each использует итератор, который отслеживает его позицию в списке. Подробнее о нюансах цикла for-each.

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

Ссылка, показанная здесь, была недействительной.

2023-09-27 18:31 java performance