Современная теория программирования использует цикл for-each. Он разработан для циклической обработки объектов коллекции, такой как массив, в строгой последовательности, от начала к концу. Благодаря удобному способу обработки, предложенному циклом for-each, этот вид цикла быстро превратился в средство, необходимое программистам. Более ранние версии языка Java не поддерживали цикл for-each, но в версию Java 2 5.0 он включен. Это расширение языка наверняка порадует всех, пишущих на языке Java.
В отличие от некоторых языков программирования, таких как С#, в котором цикл for-each реализован с помощью ключевого слова for-each. Java включает функциональные возможности цикла for-each, усовершенствуя оператор цикла for. Преимущество такого подхода заключается в том, что не требуется нового ключевого слова и не нарушается работоспособность разработанного ранее кода. Цикл for в стиле for-each (т. е. наделенный функциональными возможностями цикла for-each) иногда называют улучшенным циклом for (enhanced for loop) и в книге будут использоваться оба эти термина.
Описание цикла for-each
Общая форма записи цикла for в стиле for-each приведена в следующей строке:
foritype itr-var : iterableObj) statement-block
Здесь type— тип, a itr-var— имя переменной цикла (iteration variable), которая будет получать элементы, содержащиеся в iterabieObj, последовательно один за другим от начала к концу. Объект, на который ссылается переменная iterabieObj, должен быть массивом или объектом, реализующим новый интерфейс Iterable. В любом случае тип type должен совпадать (или быть совместимым) с типом элементов, извлекаемых из объекта iterableObj. Таким образом, в случае циклической обработки массива type должен быть совместим с базовым типом массива. В каждом проходе тела цикла извлекается очередной элемент объекта iterabieObj и запоминается в переменной itr-var. Цикл выполняется до тех пор, пока не будут извлечены все элементы.
Для того чтобы понять принцип действия цикла for-each, рассмотрим, как работает цикл for, для замены которого и был разработан цикл for-each.
В приведенном далее фрагменте используется традиционный цикл for для подсчета суммы значений, хранящихся в элементах массива:
int nums[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int sum = 0;
for (int i=0, i < 10; i++) sum +=nums{};
Для вычисления суммы считывается каждый элемент в массиве nums, начиная с первого и заканчивая последним. Следовательно, массив целиком читается строго последовательно. Эта операция выполняется вручную с помощью индексирования nums переменной i, управляющей переменной цикла. Более того, приходится явно задавать начальное и конечное значения управляющей переменной цикла, а также ее приращение.
Цикл for стиля for-each автоматизирует приведенный в предыдущем примере цикл. А именно, он устраняет необходимость устанавливать счетчик цикла, задавая начальное и конечное значения, и вручную индексировать массив. Вместо этого он автоматически проходит весь массив, получая поочередно каждый элемент, начиная с первого и заканчивая последним. Далее приведен переписанный предыдущий пример с использованием цикла for в стиле for-each:
int nums[] = {1, 2, 3, 4, 5, б, 7, 8, 9, 10 };
int sum = 0;
for(int x: nums) sum += x;
B каждом проходе тела цикла переменная х получает значение из следующего элемента массива nums. Таким образом, во время первого прохода переменная цикла х содержит значение 1, во время второго — значение 2 и т. д. При этом не только упрощается синтаксис, но и устраняются ошибки выхода за границы диапазона (boundary errors).
В листинге 4.1 приведена целиком программа, демонстрирующая подсчет суммы элементов массива с помощью цикла for в стиле for-each.
Листинг 4.1. Применение цикла for в стиле for-each
class ForEach {
public static void main(String args[]) {
int nums[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int sum = 0;
// use for-each style for to display and sum the values
for(int x : nums) {
System.out.println("Value is: " + x);
sum += x;
}
System.out.println("Summation: " + sum);
}
}
Далее приведен вывод результатов работы программы из листинга 4.1:
Value is: 1
Value is: 2
Value is: 3
Value is: 4
Value is: 5
Value is: 6
Value is: 7
Value is: 8
Value is: 9
Value is: 10
Summation: 55
Как показывает вывод программы, цикл for в стиле for-each автоматически обрабатывает массив в цикле от наименьшего значения индекса до наибольшего его значения.
Несмотря на то, что цикл for в стиле for-each повторяется до тех пор, пока не обработаны все элементы массива, можно прервать его с помощью оператора break. В листинге 4.2 приведена программа, суммирующая только первые пять элементов массива nums.
Листинг 4.2. Применение оператора break в цикле for в стиле for-each
class ForEach2 {
public static void main(String args[]) {
int sum = 0;
int nums[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Use for to display and sum the values.
for(int x : nums) {
System.out.println("Value is: " + x);
sum += x;
if(x == 5) break; // stop the loop when 5 is obtained
}
System.out.println("Summation of first 5 elements: " + sum);
}
}
Далее приведен вывод результатов работы программы из листинга 4.2:
Value is: 1
Value is: 2
Value is: 3
Value is: 4
Value is: 5
Summation of first 5 elements: 15
Ясно, что цикл for прерывается после получения пятого элемента массива.
У цикла for-each есть важная особенность. Его переменная цикла доступна только для чтения (read-only), так как она связана с обрабатываемым массивом. Другими словами, Вы не можете изменить содержимое массива, присваивая переменной цикла новое значение. Рассмотрим пример, приведенный в листинге 4.3.
Листинг 4.3. Цикл for-each по существу доступен только для чтения
class NoChange {
public static void main(String args[]) {
int nums[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for(int x : nums) {
System.out.print(x + " ");
x = x * 10; // no effect on nums
}
System.out.println();
for(int x : nums)
System.out.print(x + " ");
System.out.println();
}
}
В первом цикле for значение переменной цикла увеличивается с помощью множителя 10. Однако это присваивание никак не влияет на содержимое обрабатываемого в цикле массива nums, что иллюстрирует второй цикл for в листинге 4.3, а также приведенный далее вывод результатов работы программы:
12345678910
12345678910
|