Как работает цикл foreach в Java?

1,00
р.
Есть коллекция и цикл foreach:
List someList = new ArrayList() //add "monkey", "donkey", "skeleton key" to someList
for(String item : someList) System.out.println(item)
Как выглядит цикл for, эквивалентный циклу foreach выше? Как работает цикл foreach внутри? В чем отличия циклов for и foreach?

Ответ
Цикл foreach - это синтаксический сахар. Внешне прежде всего отличается от for отсутствием явного счетчика. Единственное практическое различие между ними заключается в том, что в случае индексируемых объектов у вас нет доступа к индексу.
Цикл foreach позволяет выполнять итерации по двум типам объектов:
T[] //массивы любого типа Объекты, реализующие интерфейс Iterable.
Цикл for, работающий с объектами Iterable
Код из вопроса
for(String item : someList) System.out.println(item)
равен коду ниже
for (Iterator i = someIterable.iterator() i.hasNext() ) { String item = i.next() System.out.println(item) }
Этот код работает для любого объекта, реализующего интерфейс Iterable.

В цикле foreach нельзя использовать метод remove(index). Вместо этого следует использовать iterator.remove(). Пример:
for (Iterator iterator = list.iterator() iterator.hasNext() ) if (iterator.next() > 10) iterator.remove()

Если писать for без использования итератора, то вот примерная реализация foreach:
for(int i = 0 i < list.size() i++) System.out.println(list.get(i))

Циклы foreach и for, работающие с массивами
String[] fruits = new String[] { "Orange", "Apple", "Pear", "Strawberry" }
for (String fruit : fruits) { // fruit is an element of the `fruits` array. }
по сути эквивалентно
for (int i = 0 i < fruits.length i++) { String fruit = fruits[i] // fruit is an element of the `fruits` array. }

foreach против for - производительность
При доступе к коллекции, foreach значительно быстрее, чем for. Однако при доступе к массивам - по крайней мере с массивами примитивов и оболочек - доступ через индексы(т.е. используя for) быстрее.
Также при вложенных циклах foreach наблюдаются проблемы с производительностью из-за создания большого количество объектов Iterator.

В Java 8 представили потоки, которые в целом работают лучше. (хоть эта информация напрямую и не относится к вопросу, но это может быть полезно)
Для работы с коллекций:
someList.stream().forEach(System.out::println)
Для работы с массивом:
Arrays.stream(someArray).forEach(System.out::println)

Документация Oracle по foreach.

UPD: Измерение производительности на JDK9
(не стоит серьезно его оценивать, т.к. мне не кажется, что я все правильно измерил)
Для замера производительности я использовал код из этого вопроса:
public static void main(String[] args) { System.out.println(getTime()) }
private static void testMethod() { //Код, время выполнения которого нужно узнать }
/** * Метод для измерения времени выполнения метода testMethod * https:/tackoverflow.com/a/2404378/7150209 */ private static double getTime() { for (int i = 0 i < 20 i ++) { //прогрев JVM testMethod() } int count = 1000 //первоначальное кол-во повтора выполнения testMethod
while(true) { long begin = System.nanoTime()
for (int i = 0 i < count i ++) testMethod()
long end = System.nanoTime()
if ((end - begin) < 1000000000) { //Прогон тестов пока суммарное выполнения count раз count *= 100000 //testMethod`a не будет равно несколько секунд continue }
return (double)(end - begin) / count } }
Как работает метод getTime() - в цикле for метод с тестируемым кодом запускается count раз. Перед началом запусков засекается время, после всех запусков из конечного времени вычитается начальное - получается время запуска count раз тестового метода. После этого время делится на count - получается усредненное время одного запуска тестового метода. Если время запуска count раз тестового метода < 10 секунд, то count увеличивается, и замер происходит заново.
В тестовом методе в циклах for и foreach я использовал: переменная = list.get(i)/array[i] для for и переменная = i для foreach.
В лямбде я использовал Arrays.stream(array).map(l -> l+1).collect(Collectors.toList()) и list.stream().map(l -> l+1).collect(Collectors.toList()), т.е. изменение элементов коллекции и создание новой коллекции, поэтому выполнение лямбд заняло больше времени.

В таблице видно, что выполнение в лямбде заняло примерно одинаковое время для коллекций и массивов. Время выполнения кода с массивом примерно в 1.5 раза быстрее, чем с коллекцией. Время выполнения цикла for и foreach для всех одинаковое.
P.S. Пример код for и foreach для коллекции(n - просто переменная):
for(int i = 0 i < list.size() i++) n = list.get(i)
и
for(int i : list) n = i