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

Рассматривать:

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

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

17.09.2008 16:44:32
Согласно JLS, он имеет две формы: stackoverflow.com/a/33232565/1216775
akhil_mittal 24.09.2018 04:40:54
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 .

1164
3.03.2018 16:16:09
Я обнаружил, что просто вызывая цикл while, как while (someList.hasMoreElements ()) {// doоверять что-то}} - приближает меня к грации кода, которую я надеялся найти, когда искал этот вопрос.
James T Snell 16.11.2012 18:10:16
Также см. Docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html, в котором объясняется цикл foreach (когда он был представлен)
PhoneixS 27.02.2014 16:12:24
для разработчиков андроид студии: import java.util.Iterator;andimport java.lang.Iterable;
dsdsdsdsd 10.05.2016 19:12:37
К сожалению, java.util.Iteratorне реализует, Iterableтак что вы не можете for(String s : (Iterator<String>)foo). Я понимаю , почему это, но это раздражает.
Christopher Schultz 18.10.2019 20:21:53

Цикл for-each в Java использует базовый механизм итератора. Так что это идентично следующему:

Iterator<String> iterator = someList.iterator();

while (iterator.hasNext()) {
  String item = iterator.next();
  System.out.println(item);
}
40
16.03.2018 13:04:16

Вот эквивалентное выражение.

for(Iterator<String> sit = someList.iterator(); sit.hasNext(); ) {
    System.out.println(sit.next());
}
10
17.09.2008 16:48:10

Это будет выглядеть примерно так. Очень грубый

for (Iterator<String> i = someList.iterator(); i.hasNext(); )
        System.out.println(i.next());

В документации Sun есть хорошая рецензия для каждого из них .

7
16.03.2018 13:05:04
for (Iterator<String> itr = someList.iterator(); itr.hasNext(); ) {
   String item = itr.next();
   System.out.println(item);
}
12
19.12.2011 09:58:20

Это подразумевается ответом nsayer, но стоит отметить, что синтаксис OP для (..) будет работать, когда «someList» - это что- то, что реализует java.lang.Iterable - это не обязательно должен быть список или некоторая коллекция из java.util. Таким образом, даже ваши собственные типы могут использоваться с этим синтаксисом.

25
16.03.2018 13:05:36
Право fd - внутренний код, когда правая часть идиомы for (:) использует int и array.length вместо выборки Iterator. forums.sun.com/thread.jspa?messageID=2743233
nsayer 17.09.2008 17:54:54

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

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

10
17.09.2008 16:53:52
В этих случаях использование removeIfможет быть правильным инструментом
ncmathsadist 10.04.2018 18:57:54

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

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

Обратите внимание, что если вам нужно использовать i.remove (); в вашем цикле или каким-либо образом получить доступ к фактическому итератору, вы не можете использовать идиому for (:), так как фактический итератор просто выводится.

[Денис Буэно]

Это подразумевается ответом nsayer, но стоит отметить, что синтаксис OP для (..) будет работать, когда «someList» - это что-то, что реализует java.lang.Iterable - это не обязательно должен быть список или некоторая коллекция из java.util. Таким образом, даже ваши собственные типы могут использоваться с этим синтаксисом.

494
16.03.2018 13:06:59

Конструкция цикла Java «для каждого» позволяет выполнять итерации по двум типам объектов:

  • T[] (массивы любого типа)
  • java.lang.Iterable<T>

Iterable<T>Интерфейс имеет только один метод: Iterator<T> iterator(). Это работает на объектах типа, Collection<T>потому что Collection<T>интерфейс расширяется Iterable<T>.

21
17.09.2008 18:04:18

Вот ответ, который не предполагает знания Java Iterators. Это менее точно, но это полезно для образования.

Во время программирования мы часто пишем код, который выглядит следующим образом:

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.

129
16.03.2018 13:12:45

Концепция цикла foreach, упомянутая в Википедии, освещена ниже:

Однако, в отличие от других конструкций цикла for, циклы foreach обычно не содержат явного счетчика : они, по сути, говорят «делай это со всем в этом наборе», а не «делай это x раз». Это позволяет избежать потенциальных ошибок, связанных с ошибками, и упрощает чтение кода.

Таким образом, концепция цикла 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.

16
16.03.2018 13:14:37

Синтаксис цикла 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
23
16.03.2018 13:16:36

foreachЦикл , добавлен в Java 5 (также называемый «усиленный цикл»), это эквивалентно использованием java.util.Iteratorсинтаксического сахара --О для одной и тех же вещей. Поэтому при чтении каждого элемента по порядку и по порядку foreachвсегда следует выбирать a через итератор, так как это более удобно и кратко.

для каждого

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напрямую. Например, попытка удалить элемент при использовании foreachcan (will?) Приведет к ConcurrentModificationException.

foreachпротив for: основные различия

Единственное практическое различие между forи foreachзаключается в том, что в случае индексируемых объектов у вас нет доступа к индексу. Пример, когда forтребуется базовый цикл:

for(int i = 0; i < array.length; i++) {
   if(i < 5) {
      // Do something special
   }  else {
      // Do other stuff
   }
}

Хотя вы можете вручную создать отдельный индекс Инт-переменный foreach,

int idx = -1;
for(int i : intArray) {
   idx++;
   ...
}

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

foreachпротив for: производительность

При доступе к коллекции, foreachэто значительно быстрее , чем основной forдоступ к массиву передачи контура в. Однако при доступе к массивам - по крайней мере с массивами примитивов и оболочек - доступ через индексы значительно быстрее.

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

Индексы 23- 40 процентов быстрее , чем итераторы при доступе intили Integerмассивов. Вот вывод из класса тестирования в нижней части этого поста, который суммирует числа в массиве primitive-int из 100 элементов (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% быстрее.

Для коллекций итераторы работают быстрее, чем индексы

Для ListOF 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});

И внесите необходимые изменения в функцию test ( int[]to List<Integer>, lengthto 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)

В одном тесте они почти эквивалентны, но с коллекциями побеждает итератор.

* Этот пост основан на двух ответах, которые я написал о переполнении стека:

Еще немного информации: что является более эффективным: цикл для каждого или итератор?

Полный класс тестирования

Я создал этот класс сравнения «время, которое требуется, чтобы сделать любые две вещи» после прочтения этого вопроса о переполнении стека:

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

}
158
16.03.2018 13:35:45
Этот ответ теперь является постом в блоге и был создан из двух связанных ответов, которые я написал: здесь и здесь . Он также включает в себя полезный класс для сравнения скорости двух функций (внизу).
aliteralmind 19.04.2014 18:23:12
Здесь только один небольшой комментарий, вы не должны категорически утверждать, что синтаксис for (:) всегда лучше для доступа к коллекциям; Если вы используете список массивов, цикл for (:) будет примерно в 2 раза медленнее, чем при использовании for (int i = 0, len = arrayList.size (); i <len; i ++). Я думаю, что вы упомянули это в ссылке [link] ( stackoverflow.com/questions/2113216/… ) в любом случае, но важно подчеркнуть это ...
Leo 26.09.2014 11:25:04
@ Leo Это хороший момент. ArrayList - это Collection, но он поддерживается массивом, поэтому нормальное значение for лучше для него.
aliteralmind 26.09.2014 13:07:40
Я думаю, что for(int value : int_array) {/* loop content */}это самый медленный в вашем тесте, потому что он синтаксически эквивалентен for(int i = 0; i < int_array.length; i++) {int value = int_array[i]; /* loop content */}, а это не то, что ваш тест сравнивает.
megaflop 20.08.2015 08:53:08
(кстати, я не говорю, что ваш тест недействителен, но, возможно, стоит отметить причины различий, чтобы люди могли выбирать, что подходит для их конкретного сценария. Если они делают int value = int_array[i];в начале их для цикл, тогда они могли бы также использовать foreach. Если по какой-то причине им тоже не нужен доступ к индексу. Короче, все зависит от контекста.)
megaflop 20.08.2015 08:56:31

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

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

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

Вывод

First
Second
Third
25
25.09.2017 15:43:15
эта случайная информация даже не дает удаленного ответа на вопрос
Tim 16.02.2018 14:55:37

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

3
18.03.2016 17:43:28
-1: это менее читабельно (как правило): даже ваш собственный пример (первый) неверен, так как пропускает первый элемент в массиве.
Ondrej Skopek 18.03.2016 17:11:50

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

Нормальный 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 является конструкцией над коллекцией, которая реализует Iterator . Помните, что ваша коллекция должна реализовывать Iterator ; в противном случае вы не можете использовать его для каждого.

Следующая строка читается как « для каждого TimerTask t в списке ».

for (TimerTask t : list)

Существует меньше шансов на ошибки в случае для каждого. Вам не нужно беспокоиться об инициализации итератора или инициализации счетчика цикла и его завершении (там, где есть место для ошибок).

8
31.03.2017 20:02:43

Как определено в JLS, цикл for-each может иметь две формы:

  1. Если тип Выражения является подтипом, 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);
24
20.10.2015 09:12:52
Самый актуальный и точный ответ. Зачарованный для действительно имеет два перевода.
Zarial 23.09.2017 11:57:39
public static Boolean Add_Tag(int totalsize)
{ List<String> fullst = new ArrayList<String>();
            for(int k=0;k<totalsize;k++)
            {
              fullst.addAll();
            }
}
4
27.10.2016 11:55:00

Как сказано во многих хороших ответах, объект должен реализовывать цикл, 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цикл.

6
31.03.2017 20:05:03

Альтернатива 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);
});
9
16.03.2018 13:38:25
Стоит упомянуть, что он добавлен в Java 1.8
TheLibrarian 27.07.2017 14:42:57
Мы не можем быть на 100% уверены, что используется одна и та же нить. Мне нравится использовать for(форму, если я хочу убедиться, что используется та же тема. Мне нравится использовать потоковую форму, если я хочу разрешить многопоточное выполнение.
Grim 18.02.2019 12:27:40

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

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

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

2
29.01.2018 08:38:51
Для этого требуется Java
BARNI 15.02.2018 07:31:06
даже отдаленно не отвечает на вопрос
Tim 16.02.2018 14:57:20

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

Вы можете найти больше о потоках здесь .

8
16.03.2018 13:40:15
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 19:10:37
List<Item> Items = obj.getItems();
for(Item item:Items)
             {
                System.out.println(item); 
             }

Перебирает все объекты в таблице Items.

-2
27.03.2018 08:15:43
Пользователь не запрашивал синтаксис
pradipgarala 6.07.2018 04:54:23

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

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

Здесь нет инициализации цикла, нет логического условия, и значение шага неявно и представляет собой простое приращение. Вот почему они считаются гораздо проще, чем обычные для циклов.

Усовершенствованные циклы for следуют этому порядку выполнения:

1) тело петли

2) повторять с шага 1 до тех пор, пока не будет пройден весь массив или коллекция

Пример - целочисленный массив

int [] intArray = {1, 3, 5, 7, 9};
for(int currentValue : intArray) {
  System.out.println(currentValue);
}

Переменная currentValue содержит текущее значение, зацикленное в массиве intArray. Обратите внимание, что нет явного значения шага - оно всегда увеличивается на 1.

Можно предположить, что двоеточие означает «в». Таким образом, расширенные состояния объявления цикла: зациклить intArray и сохранить текущее значение массива int в переменной currentValue.

Вывод:

1
3
5
7
9

Пример - String Array

Мы можем использовать цикл 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 и сохраняйте текущее значение Set в переменной currentItem. Обратите внимание, что, поскольку это Set, повторяющиеся значения String не сохраняются.

Вывод:

alpha
delta
beta
gamma

Источник: циклы в Java - полное руководство

6
2.05.2018 13:11:27

Используя более старые версии 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/

11
21.06.2018 11:05:15

В Java 8 они представили forEach. Используя этот список, карты могут быть зациклены.

Цикл Список, используя для каждого

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);
});
13
30.08.2018 13:23:15

Как правильно утверждают многие другие ответы, for each loopсинтаксический сахар - это просто тот же старый, for loopи компилятор переводит его в тот же старый цикл 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

Так что давайте удалим синтаксический сахар

Чтобы ответить на этот вопрос, я создал файл и написал две версии for each, одну с, 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) для каждого цикла были заменены простыми циклами.

2
17.04.2020 16:01:30