Учитывать:
List<String> someList = new ArrayList<String>();
// add "monkey", "donkey", "skeleton key" to someList
for (String item : someList) {
System.out.println(item);
}
Как бы выглядел эквивалентный цикл for без использования синтаксиса для каждого?
Как указано ниже, существуют различные типы цикла for в Java. Работа цикла for одинакова для всех типов и отличается только синтаксисом. * Простой цикл for (tutorialcup.com/java/…) * Улучшен цикл for - для каждого цикла (tutorialcup.com/java/java-for-loop.htm#Enhanced_Java_For_lo op) * Вложенный цикл for (tutorialcup.com/java/java-for-loop.htm#Nested_For_Loop) * Помечен для цикла (tutorialcup.com/java/java-for-loop.htm#Labeled_For_loop) tutorialcup.com/java/java-for-loop.htm
Мы можем использовать расширенный цикл for для итерации элементов для следующей коллекции: Array ArrayList Map Set LinkedList и так далее. tutorialcup.com/java/java-for-each-loop.htm




for (Iterator<String> i = someIterable.iterator(); i.hasNext();) {
String item = i.next();
System.out.println(item);
}
Обратите внимание: если вам нужно использовать i.remove(); в вашем цикле или каким-либо образом получить доступ к фактическому итератору, вы не можете использовать идиому for ( : ), поскольку фактический итератор просто подразумевается.
Как заметил Денис Буэно, этот код работает для любого объекта, реализующего Iterable интерфейс.
Кроме того, если правая часть идиомы for (:) - это array, а не объект Iterable, внутренний код использует счетчик индекса int и вместо этого проверяет array.length. Смотрите Спецификация языка Java.
Я обнаружил, что просто вызов цикла while, такого как while (someList.hasMoreElements ()) {// что-то делаем}}, приближает меня к изяществу кодирования, которое я надеялся найти, когда искал этот вопрос.
Также см. docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.htm l, который объясняет цикл foreach (когда он был введен)
для разработчиков студии Android: import java.util.Iterator; и import java.lang.Iterable;
К сожалению, java.util.Iterator не поддерживает Iterable, поэтому вы не можете использовать for(String s : (Iterator<String>)foo). Я понимаю, почему это так, но это является раздражает.
@ChristopherSchultz, вы могли бы сделать это с помощью лямбд for(String s : (Iterable<String>)() -> foo)
Итераторы не являются итераторами, потому что Iterable - это интерфейс для получения итератора. Вы ведете грузовик по выхлопной трубе.
Цикл for-each в Java использует базовый механизм итератора. Таким образом, это идентично следующему:
Iterator<String> iterator = someList.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
System.out.println(item);
}
Вот эквивалентное выражение.
for(Iterator<String> sit = someList.iterator(); sit.hasNext(); ) {
System.out.println(sit.next());
}
Это выглядело бы примерно так. Очень круто.
for (Iterator<String> i = someList.iterator(); i.hasNext(); )
System.out.println(i.next());
Есть хорошая запись о для каждого в Документация Sun.
for (Iterator<String> itr = someList.iterator(); itr.hasNext(); ) {
String item = itr.next();
System.out.println(item);
}
Это подразумевается ответом nsayer, но стоит отметить, что синтаксис OP for (..) будет работать, когда someList - это что-либо, который реализует java.lang.Iterable - это не обязательно должен быть список или некоторая коллекция из java.util. Таким образом, с этим синтаксисом можно использовать даже ваши собственные типы.
fd прав - внутренний код, когда правая часть идиомы for (:) использует int и array.length вместо выборки Iterator. форумы.sun.com/thread.jspa?messageID=2743233
Также обратите внимание, что использование метода foreach в исходном вопросе имеет некоторые ограничения, такие как невозможность удаления элементов из списка во время итерации.
Новый цикл for легче читается и устраняет необходимость в отдельном итераторе, но его можно использовать только в проходах итерации только для чтения.
В таких случаях использование removeIf может быть правильным инструментом.
Конструкция для каждого также действительна для массивов. например
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.
}
Итак, общее резюме:
[nsayer] Ниже приводится более длинная форма того, что происходит:
for(Iterator<String> i = someList.iterator(); i.hasNext(); ) { String item = i.next(); System.out.println(item); }Note that if you need to use i.remove(); in your loop, or access the actual iterator in some way, you cannot use the for( : ) idiom, since the actual Iterator is merely inferred.
It's implied by nsayer's answer, but it's worth noting that the OP's for(..) syntax will work when "someList" is anything that implements java.lang.Iterable -- it doesn't have to be a list, or some collection from java.util. Even your own types, therefore, can be used with this syntax.
Я бы не сказал, что второй пример «по существу эквивалентен первому», поскольку, если это список примитивных значений, любые изменения, которые вы вносите в значения, не изменят исходный список в примере 1, но изменит исходный список в пример 2.
Конструкция цикла «для каждого» Java позволяет выполнять итерацию по двум типам объектов:
T[](массивы любого типа)java.lang.Iterable<T>Интерфейс Iterable<T> имеет только один метод: Iterator<T> iterator(). Это работает с объектами типа Collection<T>, поскольку интерфейс Collection<T> расширяет Iterable<T>.
Вот ответ, который не предполагает знания итераторов Java. Он менее точен, но полезен для обучения.
При программировании мы часто пишем код, который выглядит следующим образом:
char[] grades = ....
for(int i = 0; i < grades.length; i++) { // for i goes from 0 to grades.length
System.out.print(grades[i]); // Print grades[i]
}
Синтаксис foreach позволяет записать этот общий шаблон более естественным и менее синтаксически зашумленным способом.
for(char grade : grades) { // foreach grade in grades
System.out.print(grade); // print that grade
}
Кроме того, этот синтаксис действителен для таких объектов, как списки или наборы, которые не поддерживают индексацию массивов, но реализуют интерфейс Java Iterable.
Концепция цикла foreach, упомянутая в Википедии, выделена ниже:
Unlike other for loop constructs, however, foreach loops usually maintain no explicit counter: they essentially say "do this to everything in this set", rather than "do this x times". This avoids potential off-by-one errors and makes code simpler to read.
Таким образом, концепция цикла foreach описывает, что цикл не использует явный счетчик, что означает, что нет необходимости использовать индексы для перемещения по списку, что избавляет пользователя от единичных ошибок. Чтобы описать общую концепцию этой ошибки «поочередно», давайте рассмотрим пример цикла для обхода списка с использованием индексов.
// In this loop it is assumed that the list starts with index 0
for(int i=0; i<list.length; i++){
}
Но предположим, что если список начинается с индекса 1, тогда этот цикл вызовет исключение, поскольку он не найдет ни одного элемента с индексом 0, и эта ошибка называется ошибкой с погашением на единицу. Таким образом, чтобы избежать этой ошибки, возникающей по отдельности, используется концепция цикла foreach. Могут быть и другие преимущества, но это то, что я считаю основной концепцией и преимуществом использования цикла foreach.
Синтаксис цикла foreach:
for (type obj:array) {...}
Пример:
String[] s = {"Java", "Coffe", "Is", "Cool"};
for (String str:s /*s is the array*/) {
System.out.println(str);
}
Выход:
Java
Coffe
Is
Cool
ПРЕДУПРЕЖДЕНИЕ. Вы можете получить доступ к элементам массива с помощью цикла foreach, но НЕ МОЖЕТЕ их инициализировать. Для этого используйте оригинальную петлю for.
ВНИМАНИЕ: вы должны сопоставить тип массива с другим объектом.
for (double b:s) // Invalid-double is not String
Если вы хотите редактировать элементы, используйте исходный цикл for следующим образом:
for (int i = 0; i < s.length-1 /*-1 because of the 0 index */; i++) {
if (i==1) //1 because once again I say the 0 index
s[i] = "2 is cool";
else
s[i] = "hello";
}
Теперь, если мы выгрузим s в консоль, мы получим:
hello
2 is cool
hello
hello
foreach петля, добавленный в Java 5 (также называемый «расширенным циклом for»), эквивалентен использованию java.util.Iterator - это синтаксический сахар для того же самого. Поэтому при чтении каждого элемента по очереди и по порядку следует всегда выбирать foreach, а не итератор, так как это более удобно и кратко.
for(int i : intList) {
System.out.println("An element in the list: " + i);
}
Iterator<Integer> intItr = intList.iterator();
while(intItr.hasNext()) {
System.out.println("An element in the list: " + intItr.next());
}
Бывают ситуации, когда вы должны использовать Iterator напрямую. Например, попытка удалить элемент при использовании foreach может (будет?) Привести к ConcurrentModificationException.
foreach против for: основные отличияЕдинственное практическое различие между for и foreach заключается в том, что в случае индексируемых объектов у вас нет доступа к индексу. Пример, когда требуется базовый цикл for:
for(int i = 0; i < array.length; i++) {
if (i < 5) {
// Do something special
} else {
// Do other stuff
}
}
Хотя вы можете вручную создать отдельную индексную int-переменную с помощью foreach,
int idx = -1;
for(int i : intArray) {
idx++;
...
}
это не рекомендуется, поскольку переменная область видимости не идеален, а базовый цикл for является просто стандартным и ожидаемым форматом для этого варианта использования.
foreach против for: производительностьПри доступе к коллекциям foreach имеет значение значительно быстрее, чем доступ к массиву основного цикла for. Однако при доступе к массивам - по крайней мере, с примитивными массивами и массивами-оболочками - доступ через индексы происходит значительно быстрее.
Индексы на 23-40 процентов быстрее, чем итераторы, при доступе к массивам int или Integer. Вот результат тестирования класса в нижней части этого поста, который суммирует числа в массиве из 100 элементов primitive-int (A - итератор, B - индекс):
[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 358,597,622 nanoseconds
Test B: 269,167,681 nanoseconds
B faster by 89,429,941 nanoseconds (24.438799231635727% faster)
[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 377,461,823 nanoseconds
Test B: 278,694,271 nanoseconds
B faster by 98,767,552 nanoseconds (25.666236154695838% faster)
[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 288,953,495 nanoseconds
Test B: 207,050,523 nanoseconds
B faster by 81,902,972 nanoseconds (27.844689860906513% faster)
[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 375,373,765 nanoseconds
Test B: 283,813,875 nanoseconds
B faster by 91,559,890 nanoseconds (23.891659337194227% faster)
[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 375,790,818 nanoseconds
Test B: 220,770,915 nanoseconds
B faster by 155,019,903 nanoseconds (40.75164734599769% faster)
[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 326,373,762 nanoseconds
Test B: 202,555,566 nanoseconds
B faster by 123,818,196 nanoseconds (37.437545972215744% faster)
Я также выполнил это для массива Integer, и индексы по-прежнему являются явным победителем, но только на 18–25 процентов быстрее.
Однако для List или Integers итераторы являются явным победителем. Просто измените массив int в тестовом классе на:
List<Integer> intList = Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100});
И внесем необходимые изменения в тестовую функцию (с int[] на List<Integer>, с length на size() и т. д.):
[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 3,429,929,976 nanoseconds
Test B: 5,262,782,488 nanoseconds
A faster by 1,832,852,512 nanoseconds (34.326681820485675% faster)
[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,907,391,427 nanoseconds
Test B: 3,957,718,459 nanoseconds
A faster by 1,050,327,032 nanoseconds (26.038700083921256% faster)
[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,566,004,688 nanoseconds
Test B: 4,221,746,521 nanoseconds
A faster by 1,655,741,833 nanoseconds (38.71935684115413% faster)
[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,770,945,276 nanoseconds
Test B: 3,829,077,158 nanoseconds
A faster by 1,058,131,882 nanoseconds (27.134122749113843% faster)
[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 3,467,474,055 nanoseconds
Test B: 5,183,149,104 nanoseconds
A faster by 1,715,675,049 nanoseconds (32.60101667104192% faster)
[C:\java_code\]java TimeIteratorVsIndexIntList 1000000
Test A: 3,439,983,933 nanoseconds
Test B: 3,509,530,312 nanoseconds
A faster by 69,546,379 nanoseconds (1.4816434912159906% faster)
[C:\java_code\]java TimeIteratorVsIndexIntList 1000000
Test A: 3,451,101,466 nanoseconds
Test B: 5,057,979,210 nanoseconds
A faster by 1,606,877,744 nanoseconds (31.269164666060377% faster)
В одном тесте они почти эквивалентны, но с коллекциями побеждает итератор.
* Этот пост основан на двух ответах, которые я написал на Stack Overflow:
Дополнительная информация: Что более эффективно: цикл for-each или итератор?
Я создал этот класс сравнения времени, необходимого для выполнения любых двух вещей, после прочтения этот вопрос в Stack Overflow:
import java.text.NumberFormat;
import java.util.Locale;
/**
<P>{@code java TimeIteratorVsIndexIntArray 1000000}</P>
@see <CODE><A HREF="https://stackoverflow.com/questions/180158/how-do-i-time-a-methods-execution-in-java">https://stackoverflow.com/questions/180158/how-do-i-time-a-methods-execution-in-java</A></CODE>
**/
public class TimeIteratorVsIndexIntArray {
public static final NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
public static final void main(String[] tryCount_inParamIdx0) {
int testCount;
// Get try-count from a command-line parameter
try {
testCount = Integer.parseInt(tryCount_inParamIdx0[0]);
}
catch(ArrayIndexOutOfBoundsException | NumberFormatException x) {
throw new IllegalArgumentException("Missing or invalid command line parameter: The number of testCount for each test. " + x);
}
//Test proper...START
int[] intArray = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100};
long lStart = System.nanoTime();
for(int i = 0; i < testCount; i++) {
testIterator(intArray);
}
long lADuration = outputGetNanoDuration("A", lStart);
lStart = System.nanoTime();
for(int i = 0; i < testCount; i++) {
testFor(intArray);
}
long lBDuration = outputGetNanoDuration("B", lStart);
outputGetABTestNanoDifference(lADuration, lBDuration, "A", "B");
}
private static final void testIterator(int[] int_array) {
int total = 0;
for(int i = 0; i < int_array.length; i++) {
total += int_array[i];
}
}
private static final void testFor(int[] int_array) {
int total = 0;
for(int i : int_array) {
total += i;
}
}
//Test proper...END
//Timer testing utilities...START
public static final long outputGetNanoDuration(String s_testName, long l_nanoStart) {
long lDuration = System.nanoTime() - l_nanoStart;
System.out.println("Test " + s_testName + ": " + nf.format(lDuration) + " nanoseconds");
return lDuration;
}
public static final long outputGetABTestNanoDifference(long l_aDuration, long l_bDuration, String s_aTestName, String s_bTestName) {
long lDiff = -1;
double dPct = -1.0;
String sFaster = null;
if (l_aDuration > l_bDuration) {
lDiff = l_aDuration - l_bDuration;
dPct = 100.00 - (l_bDuration * 100.0 / l_aDuration + 0.5);
sFaster = "B";
}
else {
lDiff = l_bDuration - l_aDuration;
dPct = 100.00 - (l_aDuration * 100.0 / l_bDuration + 0.5);
sFaster = "A";
}
System.out.println(sFaster + " faster by " + nf.format(lDiff) + " nanoseconds (" + dPct + "% faster)");
return lDiff;
}
//Timer testing utilities...END
}
Этот ответ теперь является Сообщение блога и был создан из двух связанных ответов, которые я написал: здесь и здесь. Он также включает в себя общий полезный класс для сравнения скорости двух функций (внизу).
Всего один небольшой комментарий, вы не должны категорически утверждать, что синтаксис for (:) всегда лучше для доступа к коллекциям; если вы используете список массивов, цикл for (:) будет примерно в 2 раза медленнее, чем при использовании for (int i = 0, len = arrayList.size (); i <len; i ++). Я думаю, вы все равно упомянули об этом в ссылке [ссылка] (stackoverflow.com/questions/2113216/…), но важно подчеркнуть это ...
@Leo Хороший вопрос. ArrayList - это Collection, но он поддерживается массивом, поэтому для него лучше использовать обычный for.
Я полагаю, что 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]; в начале своего for, тогда они могут также использовать foreach. Если только им по какой-то причине не нужен доступ к индексу. Короче говоря, все зависит от контекста.)
Здесь важно сравнивать яблоки с яблоками. Вопрос был о for в сравнении с foreach. Вы сравниваете индексированный доступ с итеративным доступом. Важно отметить, что foreach - это просто синтаксический обход «итератора», оборачивающий набор. Когда вы всегда используете итератор, нет заметной разницы между for и foreach, поэтому было бы несправедливо утверждать, что foreach лучше с точки зрения производительности. С технической точки зрения, он генерирует тот же код, что и обычный цикл forпри условии, что вы все еще используете итератор в цикле for.
На мой взгляд, утверждение, что foreach более производительно при работе с Collection, вводит в заблуждение. Если это связанный список в цикле for с использованием get (i), вы не проходите один раз, вы проходите 1 + 2 + .. n раз. Использование iterable - это убедиться, что вы просматриваете Коллекцию наиболее оптимальным способом без необходимости писать дополнительный код (например, current = current.getChild ()). Конечно, для ArrayList вы будете немного быстрее использовать for вместо fo foreach, потому что вам не нужно создавать промежуточный Iterator. В этом случае для меня логическое объяснение намного лучше, чем тесты
Просто наткнулся на это случайно ... и я думаю об одном моменте, на который я раньше не обращал особого внимания: если for-each определен как синтаксический сахар при итерации над Iterable, как или почему это работает в случае примитивный int[]? потому что примитивный массив на самом деле не отменяет Iterator();.
@GiorgiTsiklauri Если я правильно помню, целые числа автоматически и незаметно превращаются в целые числа.
В функциях Java 8 вы можете использовать это:
List<String> messages = Arrays.asList("First", "Second", "Third");
void forTest(){
messages.forEach(System.out::println);
}
First
Second
Third
эта случайная информация даже отдаленно не отвечает на вопрос
Идиома Java для каждой идиомы может применяться только к массивам или объектам типа * Итерируемый. Это идиома скрытый, поскольку она действительно поддерживается Iterator. Итератор программируется программистом и часто использует целочисленный индекс или узел (в зависимости от структуры данных) для отслеживания своего положения. На бумаге он медленнее, чем обычный цикл for, по крайней мере, для «линейных» структур, таких как массивы и списки, но он обеспечивает большую абстракцию.
-1: это менее читабельно (как правило): даже ваш собственный пример (первый) неверен, поскольку он не учитывает первый элемент в массиве.
Он добавляет красоту вашему коду, удаляя все основные беспорядки, связанные с циклами. Это дает ясный вид вашему коду, обоснованный ниже.
Нормальный шлейф for:
void cancelAll(Collection<TimerTask> list) {
for (Iterator<TimerTask> i = list.iterator(); i.hasNext();)
i.next().cancel();
}
Использование для каждого:
void cancelAll(Collection<TimerTask> list) {
for (TimerTask t : list)
t.cancel();
}
для каждого - это конструкция над коллекцией, которая реализует Итератор. Помните, что ваша коллекция должна реализовывать Итератор; иначе вы не сможете использовать его с for-each.
Следующая строка читается как «для каждой TimerTask t в списке.».
for (TimerTask t : list)
В случае для каждого меньше вероятность ошибки. Вам не нужно беспокоиться об инициализации итератора или инициализации счетчика цикла и его завершении (там, где есть вероятность ошибок).
Как определено в JLS, каждый цикл может иметь две формы:
Если тип Expression является подтипом Iterable, тогда перевод будет следующим:
List<String> someList = new ArrayList<String>();
someList.add("Apple");
someList.add("Ball");
for (String item : someList) {
System.out.println(item);
}
// IS TRANSLATED TO:
for(Iterator<String> stringIterator = someList.iterator(); stringIterator.hasNext(); ) {
String item = stringIterator.next();
System.out.println(item);
}
Если выражение обязательно имеет тип массива T[], тогда:
String[] someArray = new String[2];
someArray[0] = "Apple";
someArray[1] = "Ball";
for(String item2 : someArray) {
System.out.println(item2);
}
// IS TRANSLATED TO:
for (int i = 0; i < someArray.length; i++) {
String item2 = someArray[i];
System.out.println(item2);
}
В Java 8 появились потоки, которые в целом работают лучше. Мы можем использовать их как:
someList.stream().forEach(System.out::println);
Arrays.stream(someArray).forEach(System.out::println);
Самый актуальный и точный ответ. Enchansed for действительно имеет два перевода.
Я полностью не согласен с: В Java 8 появились потоки, которые в целом работают лучше., потоки реально возможны только в том случае, если вы работаете с достаточно большим набором данных. Также .stream().forEach() можно заменить на .forEach()
public static Boolean Add_Tag(int totalsize)
{ List<String> fullst = new ArrayList<String>();
for(int k=0;k<totalsize;k++)
{
fullst.addAll();
}
}
Как сказано во многих хороших ответах, объект должен реализовать Iterable interface, если он хочет использовать цикл for-each.
Я отправлю простой пример и попытаюсь по-другому объяснить, как работает цикл for-each.
Пример петли for-each:
public class ForEachTest {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("111");
list.add("222");
for (String str : list) {
System.out.println(str);
}
}
}
Затем, если мы воспользуемся javap для декомпиляции этого класса, мы получим этот образец байт-кода:
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: new #16 // class java/util/ArrayList
3: dup
4: invokespecial #18 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: ldc #19 // String 111
11: invokeinterface #21, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
16: pop
17: aload_1
18: ldc #27 // String 222
20: invokeinterface #21, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
25: pop
26: aload_1
27: invokeinterface #29, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
Как видно из последней строки примера, компилятор автоматически преобразует использование ключевого слова for-each в использование Iterator во время компиляции. Это может объяснить, почему объект, который не реализует Iterable interface, выдает Exception при попытке использовать цикл for-each.
Альтернатива forEach, чтобы избежать вашего "для каждого":
List<String> someList = new ArrayList<String>();
Вариант 1 (простой):
someList.stream().forEach(listItem -> {
System.out.println(listItem);
});
Вариант 2 (параллельное выполнение (быстрее)):
someList.parallelStream().forEach(listItem -> {
System.out.println(listItem);
});
Следует упомянуть, что он добавлен в Java 1.8
Мы не можем быть на 100% уверены, что используется один и тот же поток. Мне нравится использовать форму for(, если я хочу убедиться, что используется тот же поток. Мне нравится использовать потоковую форму, если я хочу разрешить многопоточное выполнение.
Это выглядит безумно, но это работает
List<String> someList = new ArrayList<>(); //has content
someList.forEach(System.out::println);
Это работает. Магия
Для этого требуется Java 1.8 +
даже отдаленно не отвечает на вопрос
До Java 8 вам нужно было использовать следующее:
Iterator<String> iterator = someList.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
System.out.println(item);
}
Однако с появлением Streams в Java 8 вы можете делать то же самое с гораздо меньшим синтаксисом. Например, для вашего someList вы можете:
someList.stream().forEach(System.out::println);
Вы можете узнать больше о потоках здесь.
The foreach loop, added in Java 5 (also called the "enhanced for loop"), is equivalent to using a java.util.Iterator
Java для каждого цикла (также известный как расширенный цикл for) - это упрощенная версия цикла for. Преимущество состоит в том, что нужно писать меньше кода и меньше переменных для управления. Обратной стороной является то, что у вас нет контроля над значением шага и нет доступа к индексу цикла внутри тела цикла.
Их лучше всего использовать, когда значение шага представляет собой простое приращение 1 и когда вам нужен только доступ к текущему элементу цикла. Например, если вам нужно перебрать каждый элемент в массиве или коллекции, не заглядывая вперед или за текущий элемент.
Нет ни инициализации цикла, ни логического условия, а значение шага неявно и представляет собой простое приращение. Вот почему они считаются намного проще, чем обычные циклы for.
Усовершенствованные циклы for следуют следующему порядку выполнения:
1) тело петли
2) повторяйте с шага 1, пока не пройдете весь массив или коллекцию
Пример - целочисленный массив
int [] intArray = {1, 3, 5, 7, 9};
for(int currentValue : intArray) {
System.out.println(currentValue);
}
Переменная currentValue содержит текущее значение, которое циклически перебирается в массиве intArray. Обратите внимание, что здесь нет явного значения шага - это всегда приращение на 1.
Можно подумать, что двоеточие означает «в». Таким образом, улучшенное объявление цикла for гласит: перебираем intArray и сохраняем текущее значение массива int в в переменной currentValue.
Выход:
1
3
5
7
9
Пример - массив строк
Мы можем использовать цикл for-each для перебора массива строк. В объявлении цикла говорится: выполнить цикл по массиву String myStrings и сохранить текущее значение String в в переменной currentString.
String [] myStrings = {
"alpha",
"beta",
"gamma",
"delta"
};
for(String currentString : myStrings) {
System.out.println(currentString);
}
Выход:
alpha
beta
gamma
delta
Пример - список
Расширенный цикл for также можно использовать для перебора java.util.List следующим образом:
List<String> myList = new ArrayList<String>();
myList.add("alpha");
myList.add("beta");
myList.add("gamma");
myList.add("delta");
for(String currentItem : myList) {
System.out.println(currentItem);
}
Объявление цикла гласит: перебрать список строк myList и сохранить текущее значение списка в в переменной currentItem.
Выход:
alpha
beta
gamma
delta
Пример - Установить
Расширенный цикл for также можно использовать для перебора java.util.Set следующим образом:
Set<String> mySet = new HashSet<String>();
mySet.add("alpha");
mySet.add("alpha");
mySet.add("beta");
mySet.add("gamma");
mySet.add("gamma");
mySet.add("delta");
for(String currentItem : mySet) {
System.out.println(currentItem);
}
В объявлении цикла говорится: выполнить цикл по набору строк mySet и сохранить текущее значение набора в в переменной currentItem. Обратите внимание, что, поскольку это Set, повторяющиеся строковые значения не сохраняются.
Выход:
alpha
delta
beta
gamma
Источник: Циклы в Java - полное руководство
Используя более старые версии Java, включая Java 7, вы можете использовать цикл foreach следующим образом.
List<String> items = new ArrayList<>();
items.add("A");
items.add("B");
items.add("C");
items.add("D");
items.add("E");
for(String item : items){
System.out.println(item);
}
Ниже приведен самый последний способ использования цикла foreach в Java 8.
(зациклить список с помощью лямбда-выражения forEach + или ссылки на метод)
//lambda
//Output : A,B,C,D,E
items.forEach(item->System.out.println(item));
//method reference
//Output : A,B,C,D,E
items.forEach(System.out::println);
Для получения дополнительной информации перейдите по этой ссылке.
В Java 8 они представили forEach. Используя его List, карты могут быть зациклены.
Прокрутите список, используя для каждого
List<String> someList = new ArrayList<String>();
someList.add("A");
someList.add("B");
someList.add("C");
someList.forEach(listItem -> System.out.println(listItem))
или же
someList.forEach(listItem-> {
System.out.println(listItem);
});
Зациклить карту, используя для каждого
Map<String, String> mapList = new HashMap<>();
mapList.put("Key1", "Value1");
mapList.put("Key2", "Value2");
mapList.put("Key3", "Value3");
mapList.forEach((key,value)->System.out.println("Key: " + key + " Value : " + value));
или же
mapList.forEach((key,value)->{
System.out.println("Key : " + key + " Value : " + value);
});
Как правильно утверждают многие другие ответы, foreachloop - это просто синтаксический сахар по сравнению с тем же старым forloop, и компилятор переводит его в тот же старый цикл for.
javac (open jdk) имеет переключатель -XD-printflat, который генерирует файл java с удаленным синтаксическим сахаром. полная команда выглядит так
javac -XD-printflat -d src/ MyFile.java
//-d is used to specify the directory for output java file
Чтобы ответить на этот вопрос, я создал файл и написал две версии foreach, одну с array и другую с list. мой файл java выглядел так.
import java.util.*;
public class Temp{
private static void forEachArray(){
int[] arr = new int[]{1,2,3,4,5};
for(int i: arr){
System.out.print(i);
}
}
private static void forEachList(){
List<Integer> list = Arrays.asList(1,2,3,4,5);
for(Integer i: list){
System.out.print(i);
}
}
}
Когда я compiled этот файл с указанным выше переключателем, я получил следующий результат.
import java.util.*;
public class Temp {
public Temp() {
super();
}
private static void forEachArray() {
int[] arr = new int[]{1, 2, 3, 4, 5};
for (/*synthetic*/ int[] arr$ = arr, len$ = arr$.length, i$ = 0; i$ < len$; ++i$) {
int i = arr$[i$];
{
System.out.print(i);
}
}
}
private static void forEachList() {
List list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4), Integer.valueOf(5)});
for (/*synthetic*/ Iterator i$ = list.iterator(); i$.hasNext(); ) {
Integer i = (Integer)i$.next();
{
System.out.print(i);
}
}
}
}
Вы можете видеть, что наряду с другим синтаксическим сахаром (Autoboxing) для каждого цикла были заменены простые циклы.
Думаю, это сработает:
for (Iterator<String> i = someList.iterator(); i.hasNext(); ) {
String x = i.next();
System.out.println(x);
}
Пожалуйста, объясните, почему ваш код, и попытайтесь ответить на вопрос «Как работает цикл Java 'for each'?»
Согласно JLS он имеет две формы: stackoverflow.com/a/33232565/1216775