Рассматривать:
List<String> someList = new ArrayList<String>();
// add "monkey", "donkey", "skeleton key" to someList
for (String item : someList) {
System.out.println(item);
}
Как будет for
выглядеть эквивалентный цикл без использования для каждого синтаксиса?
java
foreach
syntactic-sugar
Джей Р.
источник
источник
Ответы:
Обратите внимание, что если вам нужно использовать
i.remove();
в вашем цикле или каким-либо образом получить доступ к фактическому итератору, вы не можете использовать этуfor ( : )
идиому, поскольку фактический итератор просто выводится.Как отметил Денис Буэно, этот код работает для любого объекта, реализующего
Iterable
интерфейс .Кроме того, если правая часть
for (:)
идиомы представляет собой объект,array
а неIterable
объект, внутренний код использует счетчик индекса int и проверяет егоarray.length
. Смотрите спецификацию языка Java .источник
import java.util.Iterator;
andimport java.lang.Iterable;
java.util.Iterator
не реализует,Iterable
так что вы не можетеfor(String s : (Iterator<String>)foo)
. Я понимаю , почему это, но это раздражает.Конструкция для каждого также действительна для массивов. например
который по сути эквивалентен
Итак, общее резюме:
[nsayer] Ниже приводится более длинная форма происходящего:
[Денис Буэно]
источник
foreach
Цикл , добавлен в Java 5 (также называемый «усиленный цикл»), это эквивалентно использованиемjava.util.Iterator
синтаксического сахара --О для одной и тех же вещей. Поэтому при чтении каждого элемента по порядку и по порядкуforeach
всегда следует выбирать a через итератор, так как это более удобно и кратко.для каждого
Итератор
Есть ситуации, когда вы должны использовать
Iterator
напрямую. Например, попытка удалить элемент при использованииforeach
can (will?) Приведет кConcurrentModificationException
.foreach
противfor
: основные различияЕдинственное практическое различие между
for
иforeach
заключается в том, что в случае индексируемых объектов у вас нет доступа к индексу. Пример, когдаfor
требуется базовый цикл:Хотя вы можете вручную создать отдельный индекс Инт-переменный
foreach
,это не рекомендуется, поскольку переменная область не идеальна, а базовый
for
цикл - это просто стандартный и ожидаемый формат для этого варианта использования.foreach
противfor
: производительностьПри доступе к коллекции,
foreach
это значительно быстрее , чем основнойfor
доступ к массиву передачи контура в. Однако при доступе к массивам - по крайней мере с массивами примитивов и оболочек - доступ через индексы значительно быстрее.Синхронизация разницы между итератором и доступом к индексу для примитивных int-массивов
Индексы 23- 40 процентов быстрее , чем итераторы при доступе
int
илиInteger
массивов. Ниже приведен вывод из класса тестирования в нижней части этого поста, который суммирует числа в массиве primitive-int из 100 элементов (A - итератор, B - индекс):Я также выполнил это для
Integer
массива, и индексы по-прежнему явный победитель, но только на 18-25% быстрее.Для коллекций итераторы работают быстрее, чем индексы
Для
List
OFIntegers
, однако, итераторы явным победителем. Просто измените массив int в классе теста на:И внесите необходимые изменения в функцию test (
int[]
toList<Integer>
,length
tosize()
и т. Д.):В одном тесте они почти эквивалентны, но с коллекциями побеждает итератор.
* Этот пост основан на двух ответах, которые я написал о переполнении стека:
Использование и синтаксис для каждого цикла в Java
Должен ли я использовать итератор или forloop для итерации?
Еще немного информации: что является более эффективным: цикл для каждого или итератор?
Полный класс тестирования
Я создал этот класс «сравнивать время, которое требуется, чтобы делать любые две вещи» после прочтения этого вопроса о переполнении стека:
источник
for(int value : int_array) {/* loop content */}
это самый медленный в вашем тесте, потому что он синтаксически эквивалентенfor(int i = 0; i < int_array.length; i++) {int value = int_array[i]; /* loop content */}
, а это не то, что ваш тест сравнивает.int value = int_array[i];
в начале их для цикл, тогда они могут также использовать foreach. Если по какой-то причине им тоже не нужен доступ к индексу. Короче, все зависит от контекста.)Вот ответ, который не предполагает знания Java Iterators. Это менее точно, но это полезно для образования.
При программировании мы часто пишем код, который выглядит следующим образом:
Синтаксис foreach позволяет писать этот общий шаблон более естественным и менее синтаксически шумным способом.
Кроме того, этот синтаксис действителен для таких объектов, как списки или наборы, которые не поддерживают индексацию массива, но которые реализуют интерфейс Java Iterable.
источник
Цикл for-each в Java использует базовый механизм итератора. Так что это идентично следующему:
источник
В функциях Java 8 вы можете использовать это:
Вывод
источник
Это подразумевается ответом nsayer, но стоит отметить, что синтаксис OP для (..) будет работать, когда «someList» - это что- то, что реализует java.lang.Iterable - это не обязательно должен быть список или некоторая коллекция из java.util. Таким образом, даже ваши собственные типы могут использоваться с этим синтаксисом.
источник
Как определено в JLS, цикл for-each может иметь две формы:
Если тип Выражения является подтипом,
Iterable
тогда перевод выглядит так:Если выражение обязательно имеет тип массива,
T[]
тогда:Java 8 представила потоки, которые в целом работают лучше. Мы можем использовать их как:
источник
Синтаксис цикла foreach:
Пример:
Вывод:
ВНИМАНИЕ: Вы можете получить доступ к элементам массива с помощью цикла foreach, но НЕ можете их инициализировать. Используйте оригинальный
for
цикл для этого.ВНИМАНИЕ: Вы должны сопоставить тип массива с другим объектом.
Если вы хотите редактировать элементы, используйте оригинальный
for
цикл следующим образом:Теперь, если мы сбросим s в консоль, мы получим:
источник
Конструкция цикла Java «для каждого» позволяет выполнять итерации по двум типам объектов:
T[]
(массивы любого типа)java.lang.Iterable<T>
Iterable<T>
Интерфейс имеет только один метод:Iterator<T> iterator()
. Это работает с объектами типа,Collection<T>
потому чтоCollection<T>
интерфейс расширяетсяIterable<T>
.источник
Концепция цикла foreach, упомянутая в Википедии, освещена ниже:
Таким образом, концепция цикла foreach описывает, что цикл не использует какой-либо явный счетчик, что означает, что нет необходимости использовать индексы для перемещения по списку, таким образом, он спасает пользователя от ошибки «один на один». Чтобы описать общую концепцию этой ошибки, давайте возьмем пример цикла для перемещения по списку с использованием индексов.
Но предположим, что если список начинается с индекса 1, то этот цикл будет генерировать исключение, так как он не найдет элемент с индексом 0, и эта ошибка называется ошибкой «один за другим». Поэтому, чтобы избежать этой ошибки, используется концепция цикла foreach. Могут быть и другие преимущества, но это то, что я считаю основной концепцией и преимуществом использования цикла foreach.
источник
В Java 8 они представили forEach. Используя этот список, карты могут быть зациклены.
Цикл Список, используя для каждого
или
Зациклить карту, используя для каждого
или
источник
источник
Используя более старые версии Java, в том числе
Java 7
вы можете использоватьforeach
цикл следующим образом.Ниже приводится самый последний способ использования
foreach
цикла вJava 8
(зациклить список с помощью
forEach
лямбда-выражения или ссылки на метод)Для получения дополнительной информации перейдите по этой ссылке.
https://www.mkyong.com/java8/java-8-foreach-examples/
источник
Вот эквивалентное выражение.
источник
Также обратите внимание, что использование метода «foreach» в исходном вопросе имеет некоторые ограничения, такие как невозможность удаления элементов из списка во время итерации.
Новый цикл for проще для чтения и устраняет необходимость в отдельном итераторе, но он действительно применим только для проходов только для чтения.
источник
removeIf
может быть правильным инструментомАльтернатива forEach для того, чтобы избежать вашего «для каждого»:
Вариант 1 (простой):
Вариант 2 (параллельное выполнение (быстрее)):
источник
for(
форму, если я хочу убедиться, что используется одна и та же тема. Мне нравится использовать потоковую форму, если я хочу разрешить многопоточное выполнение.Это добавляет красоты вашему коду, удаляя все основные циклы беспорядка. Это дает чистый взгляд на ваш код, приведенный ниже.
Нормальный
for
цикл:Используя для каждого:
for-each является конструкцией над коллекцией, которая реализует Iterator . Помните, что ваша коллекция должна реализовывать Iterator ; в противном случае вы не можете использовать его для каждого.
Следующая строка читается как « для каждого TimerTask t в списке ».
Существует меньше шансов на ошибки в случае для каждого. Вам не нужно беспокоиться об инициализации итератора или инициализации счетчика цикла и его завершении (там, где есть место для ошибок).
источник
До Java 8 вам необходимо использовать следующее:
Однако с появлением Streams в Java 8 вы можете делать то же самое с гораздо меньшим синтаксисом. Например, для вашего
someList
вы можете сделать:Вы можете найти больше о потоках здесь .
источник
The foreach loop, added in Java 5 (also called the "enhanced for loop"), is equivalent to using a java.util.Iterator
Это будет выглядеть примерно так. Очень грубый
В документации Sun есть хорошая рецензия для каждого из них .
источник
Как сказано во многих хороших ответах, объект должен реализовывать цикл,
Iterable interface
если он хочет использоватьfor-each
цикл.Я опубликую простой пример и попытаюсь по-другому объяснить, как работает
for-each
цикл.for-each
Пример цикла:Затем, если мы используем
javap
для декомпиляции этого класса, мы получим этот пример байт-кода:Как мы видим из последней строки примера, компилятор автоматически преобразует использование
for-each
ключевого слова в использование во времяIterator
компиляции. Это может объяснить, почему объект, который не реализуетIterable interface
, будет выдавать,Exception
когда он пытается использоватьfor-each
цикл.источник
Java для каждого цикла ( так называемый цикл усиления) представляет собой упрощенную версию для цикла. Преимущество состоит в том, что меньше кода для написания и меньше переменных для управления. Недостатком является то, что у вас нет контроля над значением шага и нет доступа к индексу цикла внутри тела цикла.
Их лучше всего использовать, когда значение шага является простым приращением 1 и когда вам нужен только доступ к текущему элементу цикла. Например, если вам нужно перебрать каждый элемент в массиве или коллекции, не заглядывая вперед или позади текущего элемента.
Здесь нет инициализации цикла, нет логического условия, а значение шага неявно и представляет собой простое приращение. Вот почему они считаются намного проще, чем обычные для циклов.
Усовершенствованные циклы for следуют этому порядку выполнения:
1) тело петли
2) повторять с шага 1 до тех пор, пока не будет пройден весь массив или коллекция
Пример - Целочисленный Массив
Переменная currentValue содержит текущее значение, зацикленное в массиве intArray. Обратите внимание, что нет явного значения шага - оно всегда увеличивается на 1.
Можно предположить, что двоеточие означает «в». Таким образом, расширенные состояния объявления цикла: перебирайте intArray и сохраняйте текущее значение массива int в переменной currentValue.
Вывод:
Пример - String Array
Мы можем использовать цикл for-each для итерации по массиву строк. Объявление цикла гласит: зациклите массив String myStrings и сохраните текущее значение String в переменной currentString.
Вывод:
Пример - Список
Усовершенствованный цикл for также можно использовать для перебора java.util.List следующим образом:
Объявление цикла сообщает: переберите список строк myList и сохраните текущее значение списка в переменной currentItem.
Вывод:
Пример - Установить
Усовершенствованный цикл for также можно использовать для перебора java.util.Set следующим образом:
Объявление цикла гласит: зациклите набор строк mySet и сохраните текущее значение Set в переменной currentItem. Обратите внимание, что, поскольку это Set, повторяющиеся значения String не сохраняются.
Вывод:
Источник: циклы в Java - полное руководство
источник
источник
Идиома Java for-each может применяться только к массивам или объектам типа * Iterable . Эта идиома неявная, поскольку она действительно поддерживается итератором. Итератор программируется программистом и часто использует целочисленный индекс или узел (в зависимости от структуры данных) для отслеживания своей позиции. На бумаге он медленнее обычного цикла for, наименьший для «линейных» структур, таких как массивы и списки, но он обеспечивает большую абстракцию.
источник
Это выглядит сумасшедшим, но эй, это работает
Это работает. магия
источник
Как правильно утверждают многие другие ответы,
for
each
loop
синтаксический сахар - это просто тот же старый,for
loop
и компилятор переводит его в тот же старый цикл for.javac (open jdk) имеет переключатель
-XD-printflat
, который генерирует файл java со всеми удаленными синтаксическими сахарами. полная команда выглядит следующим образомТак что давайте удалим синтаксический сахар
Чтобы ответить на этот вопрос, я создал файл и написал две версии
for
each
, одну с,array
а другую сlist
. мойjava
файл выглядел такКогда я
compiled
этот файл с вышеупомянутым переключателем, я получил следующий вывод.Вы можете видеть, что наряду с другим синтаксическим сахаром (Autoboxing) для каждого цикла были изменены простые циклы.
источник
Перебирает все объекты в таблице Items.
источник