Рассмотреть:

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

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

1623
Jay R. 17 Сен 2008 в 20:44
3
Согласно JLS он имеет две формы: stackoverflow.com/a/33232565/1216775
 – 
akhil_mittal
24 Сен 2018 в 07:40
Как указано ниже, существуют различные типы цикла for в Java. Работа цикла for одинакова для всех типов и отличается только синтаксисом. * Простой цикл for (tutorialcup.com/java/… ) * Улучшено для цикла - для каждого цикла (tutorialcup.com/java/ java-for-loop.htm # Enhanced_Java_For_loop) * Вложенный цикл 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 Июл 2020 в 09:35
Мы можем использовать расширенный цикл for для итерации элементов для следующей коллекции: Array ArrayList Map Set LinkedList и так далее. tutorialcup.com/java/java-for-each-loop.htm < / а>
 – 
Rahul Gupta
21 Июл 2020 в 15:16

28 ответов

Лучший ответ
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 .

1235
Sotirios Delimanolis 3 Мар 2018 в 19:16
20
Я обнаружил, что просто вызываю цикл while, например while (someList.hasMoreElements ()) {// делаем что-то}} - приближает меня к благодати кодирования, которую я надеялся найти, когда искал по этому вопросу.
 – 
James T Snell
16 Ноя 2012 в 22:10
8
См. Также docs.oracle.com/javase/1.5. 0 / docs / guide / language / foreach.html, которые объясняют цикл foreach (когда он был представлен)
 – 
PhoneixS
27 Фев 2014 в 20:12
1
Для разработчиков студии Android: import java.util.Iterator; и import java.lang.Iterable;
 – 
dsdsdsdsd
10 Май 2016 в 22:12
К сожалению, java.util.Iterator не реализует Iterable, поэтому вы не можете for(String s : (Iterator<String>)foo). Я понимаю, почему это так, но это меня раздражает.
 – 
Christopher Schultz
18 Окт 2019 в 23:21
Это можно сделать с помощью лямбда-выражений for(String s : (Iterable<String>)() -> foo)
 – 
Lino
2 Июл 2020 в 11:25

Добавлен цикл foreach в Java 5 (также называемой "расширенным for loop "), эквивалентно использованию 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

}
173
Peter Mortensen 16 Мар 2018 в 16:35
6
Теперь этот ответ представляет собой сообщение в блоге и был создан на основе двух связанных ответов, которые Я написал: здесь и здесь. Он также включает в себя общий полезный класс для сравнения скорости двух функций (внизу).
 – 
aliteralmind
19 Апр 2014 в 22:23
2
Всего один небольшой комментарий, вы не должны категорически утверждать, что синтаксис for (:) всегда лучше для доступа к коллекциям; если вы используете список массивов, цикл for (:) будет примерно в 2 раза медленнее, чем при использовании for (int i = 0, len = arrayList.size (); i stackoverflow.com/questions/2113216/…) в любом случае, но важно подчеркнуть это ...
 – 
Leo
26 Сен 2014 в 15:25
Это хороший момент. ArrayList - это Collection, но он поддерживается массивом, поэтому для него лучше использовать нормальный for.
 – 
aliteralmind
26 Сен 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 Авг 2015 в 11:53
(кстати, я не говорю, что ваш тест недействителен, но, возможно, стоит отметить причины разницы, чтобы люди могли выбрать то, что подходит для их конкретного сценария. Если они выполняют int value = int_array[i]; в начало их цикла for, то они могут также использовать foreach. Если только им по какой-то причине не нужен доступ к индексу. Короче говоря, все зависит от контекста.)
 – 
daiscog
20 Авг 2015 в 11:56

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

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

while (iterator.hasNext()) {
  String item = iterator.next();
  System.out.println(item);
}
42
Peter Mortensen 16 Мар 2018 в 16:04

Как определено в JLS для каждого цикла. может иметь две формы:

  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);
28
akhil_mittal 20 Окт 2015 в 12:12
2
Самый актуальный и точный ответ. Enchansed for действительно имеет два перевода.
 – 
Zarial
23 Сен 2017 в 14:57
1
Я полностью не согласен с: Java 8 представила потоки, которые в целом работают лучше. потоки реально возможны только в том случае, если вы работаете с достаточно большим набором данных. Также .stream().forEach() можно заменить на .forEach()
 – 
Lino
11 Мар 2021 в 13:42

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

25
Peter Mortensen 16 Мар 2018 в 16:05
2
Fd прав - внутренний код, когда правая часть идиомы for (:) использует int и array.length вместо выборки Iterator. forum.sun.com/thread.jspa?messageID=2743233
 – 
nsayer
17 Сен 2008 в 21:54

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

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

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

Выход

First
Second
Third
23
Jrovalle 25 Сен 2017 в 18:43
12
Эта случайная информация даже отдаленно не отвечает на вопрос
 – 
Tim
16 Фев 2018 в 17:55

Синтаксис цикла 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
Peter Mortensen 16 Мар 2018 в 16:16

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

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

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

21
Ryan Delucchi 17 Сен 2008 в 22:04

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

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

Таким образом, концепция цикла 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
Peter Mortensen 16 Мар 2018 в 16:14

В 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);
});
16
vivekkurien 30 Авг 2018 в 16:23
for (Iterator<String> itr = someList.iterator(); itr.hasNext(); ) {
   String item = itr.next();
   System.out.println(item);
}
12
Roger Lindsjö 19 Дек 2011 в 13:58

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

for(Iterator<String> sit = someList.iterator(); sit.hasNext(); ) {
    System.out.println(sit.next());
}
11
Hank 17 Сен 2008 в 20:48

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

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

10
billjamesdev 17 Сен 2008 в 20:53
1
В таких случаях использование removeIf может быть правильным инструментом
 – 
ncmathsadist
10 Апр 2018 в 21:57

Альтернатива 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
Peter Mortensen 16 Мар 2018 в 16:38
2
Следует упомянуть, что он добавлен в Java 1.8
 – 
TheLibrarian
27 Июл 2017 в 17:42
Мы не можем быть на 100% уверены, что используется один и тот же поток. Мне нравится использовать форму for(, если я хочу убедиться, что используется тот же поток. Мне нравится использовать потоковую форму, если я хочу разрешить многопоточное выполнение.
 – 
Grim
18 Фев 2019 в 15:27

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

Обычный for цикл:

void cancelAll(Collection<TimerTask> list) {
    for (Iterator<TimerTask> i = list.iterator(); i.hasNext();)
         i.next().cancel();
}

Использование for-each:

void cancelAll(Collection<TimerTask> list) {
    for (TimerTask t : list)
        t.cancel();
}

for-each - это конструкция над коллекцией, реализующая Iterator . Помните, что ваша коллекция должна реализовывать Iterator ; в противном случае вы не сможете использовать его с for-each.

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

for (TimerTask t : list)

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

8
Peter Mortensen 31 Мар 2017 в 23:02

До 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
Peter Mortensen 16 Мар 2018 в 16:40
The foreach loop, added in Java 5 (also called the "enhanced for loop"), is equivalent to using a java.util.Iterator
 – 
Alex78191
21 Ноя 2019 в 22:10

Как сказано во многих хороших ответах, объект должен реализовать 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
Peter Mortensen 31 Мар 2017 в 23:05

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

Выход:

alpha
delta
beta
gamma

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

6
gomisha 2 Май 2018 в 16:11
public static Boolean Add_Tag(int totalsize)
{ List<String> fullst = new ArrayList<String>();
            for(int k=0;k<totalsize;k++)
            {
              fullst.addAll();
            }
}
4
dur 27 Окт 2016 в 14:55

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

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

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

2
Rei Brown 29 Янв 2018 в 11:38
1
Для этого требуется Java 1.8 +
 – 
BARNI
15 Фев 2018 в 10:31
2
Даже отдаленно не отвечает на вопрос
 – 
Tim
16 Фев 2018 в 17:57

Код будет:

import java.util.ArrayList;
import java.util.List;

public class ForLoopDemo {

  public static void main(String[] args) {
    
    List<String> someList = new ArrayList<String>();
    
    someList.add("monkey");
    someList.add("donkey");
    someList.add("skeleton key");
    
    //Iteration using For Each loop
    System.out.println("Iteration using For Each loop:");
    for (String item : someList) {
      System.out.println(item);
    }
    
    //Iteration using normal For loop
    System.out.println("\nIteration using normal For loop:");
    for (int index = 0; index < someList.size(); index++) {
      System.out.println(someList.get(index));
    }
  }
}
0
Java-Dev 26 Мар 2021 в 13:29

Вот ответ, который не предполагает знания итераторов 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.

130
Peter Mortensen 16 Мар 2018 в 16:12

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

12
Dulith De Costa 21 Июн 2018 в 14:05

Думаю, это сработает:

for (Iterator<String> i = someList.iterator(); i.hasNext(); ) {
   String x = i.next();
   System.out.println(x);
}
0
nabayram 26 Янв 2021 в 21:09
Пожалуйста, объясните, почему ваш код, и попытайтесь ответить на вопрос «Как работает цикл Java 'for each'?»
 – 
phoenixstudio
26 Янв 2021 в 21:27

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

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 (:), поскольку фактический Iterator просто выводится.

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

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

521
Peter Mortensen 16 Мар 2018 в 16:06
1
Я бы не сказал, что второй пример «по существу эквивалентен первому», поскольку, если это список примитивных значений, любые изменения, которые вы вносите в значения, не изменят исходный список в примере 1, но изменит исходный список в пример 2.
 – 
Kosaro
3 Сен 2020 в 21:21

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

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

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

5
mightyWOZ 17 Апр 2020 в 19:01

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

3
TheArchon 18 Мар 2016 в 20:43
-1: это менее читабельно (как правило): даже ваш собственный пример (первый) неверен, поскольку он не учитывает первый элемент в массиве.
 – 
Ondrej Skopek
18 Мар 2016 в 20:11