17

В деталях: как работает цикл 'for each' в Java?

12

Описание проблемы:

Я новичок в Java и столкнулся с вопросом по поводу итерации по списку. У меня есть следующий код:

List<String> someList = new ArrayList<>();
// добавляем "monkey", "donkey", "skeleton key" в someList

for (String item : someList) {
    System.out.println(item);
}

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

Кроме того, я заметил, что новички в Java часто сталкиваются с проблемами, когда пытаются модифицировать исходные данные с помощью нового стиля цикла foreach. Я нашел информацию о том, что не стоит пытаться изменить переменную итерации в цикле foreach, потому что это не изменит исходные данные. Можно ли использовать другие конструкции для решения этой проблемы?

Спасибо за любые советы!

5 ответ(ов)

1

Вот ответ, который не предполагает знания о Java Итераторах. Он менее точен, но полезен для обучения.

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

char[] grades = ....
for(int i = 0; i < grades.length; i++) {   // переменная i проходит от 0 до grades.length
    System.out.print(grades[i]);           // выводим grades[i]
}

Синтаксис for-each позволяет записать этот распространённый паттерн более естественным и менее загромождённым синтаксисом.

for(char grade : grades) {   // для каждого grade в grades
    System.out.print(grade); // выводим этот grade
}

Кроме того, этот синтаксис также применим к объектам, таким как Lists или Sets, которые не поддерживают индексирование массивов, но реализуют интерфейс Iterable в Java.

0

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

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

while (iterator.hasNext()) {
  String item = iterator.next();
  System.out.println(item);
}

Таким образом, можно сказать, что использование for-each позволяет писать более лаконичный и читаемый код, но за кулисами он по-прежнему работает с итераторами.

0

Синтаксис цикла foreach выглядит так:

for (тип объект: массив) {...}

Пример:

String[] s = {"Java", "Coffe", "Is", "Cool"};
for (String str : s /*s — это массив*/) {
    System.out.println(str);
}

Вывод:

Java
Coffe
Is
Cool

ВНИМАНИЕ: Вы можете получать доступ к элементам массива с помощью цикла foreach, но вы НЕ можете их инициализировать. Для этого используйте обычный цикл for.

ВНИМАНИЕ: Тип массива должен совпадать с типом объекта.

for (double b : s) // Неверно: double не является String

Если вы хотите изменять элементы, используйте обычный цикл for, как в следующем примере:

for (int i = 0; i < s.length - 1 /*-1 из-за нулевого индекса*/; i++) {
    if (i == 1) // 1, потому что снова указываю на нулевой индекс
        s[i] = "2 is cool";
    else
        s[i] = "hello";
}

Теперь, если мы выведем массив s в консоль, мы получим:

hello
2 is cool
hello
hello
0

Конструктция цикла "for-each" в Java позволяет итерироваться по двум типам объектов:

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

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

0

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

Вот как выглядит ваш пример:

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

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

Вывод

First
Second
Third

В этом коде мы создаем список строк с помощью Arrays.asList(), а затем используем метод forEach() для печати каждой строки на консоль. Ссылка на метод System.out::println является удобным способом передать логику вывода в метод forEach(). Таким образом, у вас получается лаконичный и читаемый код.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь