Как работает цикл Java «для каждого»?

Учитывать:

List<String> someList = new ArrayList<String>();
// add "monkey", "donkey", "skeleton key" to someList
for (String item : someList) {
    System.out.println(item);
}

Как бы выглядел эквивалентный цикл for без использования синтаксиса для каждого?

Согласно JLS он имеет две формы: stackoverflow.com/a/33232565/1216775

akhil_mittal 24.09.2018 07:40

Как указано ниже, существуют различные типы цикла 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

Rahul Gupta 21.07.2020 09:35

Мы можем использовать расширенный цикл for для итерации элементов для следующей коллекции: Array ArrayList Map Set LinkedList и так далее. tutorialcup.com/java/java-for-each-loop.htm

Rahul Gupta 21.07.2020 15:16
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1 562
3
2 663 375
27
Перейти к ответу Данный вопрос помечен как решенный

Ответы 27

Ответ принят как подходящий

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 ()) {// что-то делаем}}, приближает меня к изяществу кодирования, которое я надеялся найти, когда искал этот вопрос.

James T Snell 16.11.2012 22:10

Также см. docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.htm‌ l, который объясняет цикл foreach (когда он был введен)

PhoneixS 27.02.2014 20:12

для разработчиков студии Android: import java.util.Iterator; и import java.lang.Iterable;

dsdsdsdsd 10.05.2016 22:12

К сожалению, java.util.Iterator не поддерживает Iterable, поэтому вы не можете использовать for(String s : (Iterator<String>)foo). Я понимаю, почему это так, но это является раздражает.

Christopher Schultz 18.10.2019 23:21

@ChristopherSchultz, вы могли бы сделать это с помощью лямбд for(String s : (Iterable<String>)() -> foo)

Lino 02.07.2020 11:25

Итераторы не являются итераторами, потому что Iterable - это интерфейс для получения итератора. Вы ведете грузовик по выхлопной трубе.

nsayer 06.07.2020 19:35

Цикл 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

nsayer 17.09.2008 21:54

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

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

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

ncmathsadist 10.04.2018 21:57

Конструкция для каждого также действительна для массивов. например

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.

Kosaro 03.09.2020 21:21

Конструкция цикла «для каждого» 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. Однако при доступе к массивам - по крайней мере, с примитивными массивами и массивами-оболочками - доступ через индексы происходит значительно быстрее.

Разница во времени между итератором и доступом к индексу для примитивных int-массивов

Индексы на 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;

/**
   &lt;P&gt;{@code java TimeIteratorVsIndexIntArray 1000000}&lt;/P&gt;

   @see  &lt;CODE&gt;&lt;A HREF=&quot;https://stackoverflow.com/questions/180158/how-do-i-time-a-methods-execution-in-java&quot;&gt;https://stackoverflow.com/questions/180158/how-do-i-time-a-methods-execution-in-java&lt;/A&gt;&lt;/CODE&gt;
 **/
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

}

Этот ответ теперь является Сообщение блога и был создан из двух связанных ответов, которые я написал: здесь и здесь. Он также включает в себя общий полезный класс для сравнения скорости двух функций (внизу).

aliteralmind 19.04.2014 22:23

Всего один небольшой комментарий, вы не должны категорически утверждать, что синтаксис for (:) всегда лучше для доступа к коллекциям; если вы используете список массивов, цикл for (:) будет примерно в 2 раза медленнее, чем при использовании for (int i = 0, len = arrayList.size (); i <len; i ++). Я думаю, вы все равно упомянули об этом в ссылке [ссылка] (stackoverflow.com/questions/2113216/…), но важно подчеркнуть это ...

Leo 26.09.2014 15:25

@Leo Хороший вопрос. ArrayList - это Collection, но он поддерживается массивом, поэтому для него лучше использовать обычный for.

aliteralmind 26.09.2014 17:07

Я полагаю, что for(int value : int_array) {/* loop content */} является самым медленным в вашем тесте, потому что он синтаксически эквивалентен for(int i = 0; i < int_array.length; i++) {int value = int_array[i]; /* loop content */}, что не то, что сравнивает ваш тест.

daiscog 20.08.2015 11:53

(кстати, я не говорю, что ваш тест недействителен, но, возможно, стоит отметить причины разницы, чтобы люди могли выбрать то, что подходит для их конкретного сценария. Если они делают int value = int_array[i]; в начале своего for, тогда они могут также использовать foreach. Если только им по какой-то причине не нужен доступ к индексу. Короче говоря, все зависит от контекста.)

daiscog 20.08.2015 11:56

Здесь важно сравнивать яблоки с яблоками. Вопрос был о for в сравнении с foreach. Вы сравниваете индексированный доступ с итеративным доступом. Важно отметить, что foreach - это просто синтаксический обход «итератора», оборачивающий набор. Когда вы всегда используете итератор, нет заметной разницы между for и foreach, поэтому было бы несправедливо утверждать, что foreach лучше с точки зрения производительности. С технической точки зрения, он генерирует тот же код, что и обычный цикл forпри условии, что вы все еще используете итератор в цикле for.

Christopher Schultz 18.10.2019 23:35

На мой взгляд, утверждение, что foreach более производительно при работе с Collection, вводит в заблуждение. Если это связанный список в цикле for с использованием get (i), вы не проходите один раз, вы проходите 1 + 2 + .. n раз. Использование iterable - это убедиться, что вы просматриваете Коллекцию наиболее оптимальным способом без необходимости писать дополнительный код (например, current = current.getChild ()). Конечно, для ArrayList вы будете немного быстрее использовать for вместо fo foreach, потому что вам не нужно создавать промежуточный Iterator. В этом случае для меня логическое объяснение намного лучше, чем тесты

Walfrat 10.06.2020 11:14

Просто наткнулся на это случайно ... и я думаю об одном моменте, на который я раньше не обращал особого внимания: если for-each определен как синтаксический сахар при итерации над Iterable, как или почему это работает в случае примитивный int[]? потому что примитивный массив на самом деле не отменяет Iterator();.

Giorgi Tsiklauri 21.09.2020 09:47

@GiorgiTsiklauri Если я правильно помню, целые числа автоматически и незаметно превращаются в целые числа.

aliteralmind 21.09.2020 12:07

В функциях Java 8 вы можете использовать это:

List<String> messages = Arrays.asList("First", "Second", "Third");

void forTest(){
    messages.forEach(System.out::println);
}

Выход

First
Second
Third

эта случайная информация даже отдаленно не отвечает на вопрос

Tim 16.02.2018 17:55

Идиома Java для каждой идиомы может применяться только к массивам или объектам типа * Итерируемый. Это идиома скрытый, поскольку она действительно поддерживается Iterator. Итератор программируется программистом и часто использует целочисленный индекс или узел (в зависимости от структуры данных) для отслеживания своего положения. На бумаге он медленнее, чем обычный цикл for, по крайней мере, для «линейных» структур, таких как массивы и списки, но он обеспечивает большую абстракцию.

-1: это менее читабельно (как правило): даже ваш собственный пример (первый) неверен, поскольку он не учитывает первый элемент в массиве.

Ondrej Skopek 18.03.2016 20:11

Он добавляет красоту вашему коду, удаляя все основные беспорядки, связанные с циклами. Это дает ясный вид вашему коду, обоснованный ниже.

Нормальный шлейф 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, каждый цикл может иметь две формы:

  1. Если тип 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);
    }
    
  2. Если выражение обязательно имеет тип массива 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 действительно имеет два перевода.

Zarial 23.09.2017 14:57

Я полностью не согласен с: В Java 8 появились потоки, которые в целом работают лучше., потоки реально возможны только в том случае, если вы работаете с достаточно большим набором данных. Также .stream().forEach() можно заменить на .forEach()

Lino 11.03.2021 13:42

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

TheLibrarian 27.07.2017 17:42

Мы не можем быть на 100% уверены, что используется один и тот же поток. Мне нравится использовать форму for(, если я хочу убедиться, что используется тот же поток. Мне нравится использовать потоковую форму, если я хочу разрешить многопоточное выполнение.

Grim 18.02.2019 15:27

Это выглядит безумно, но это работает

List<String> someList = new ArrayList<>(); //has content
someList.forEach(System.out::println);

Это работает. Магия

Для этого требуется Java 1.8 +

BARNI 15.02.2018 10:31

даже отдаленно не отвечает на вопрос

Tim 16.02.2018 17:57

До 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

Alex78191 21.11.2019 22:10

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);

Для получения дополнительной информации перейдите по этой ссылке.

https://www.mkyong.com/java8/java-8-foreach-examples/

В 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'?»

phoenixstudio 26.01.2021 21:27

Другие вопросы по теме