Освой Java играючи
/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000
Конструкция for управляет циклами. Команда выполняется до тех пор, пока управляющее логическое выражение не станет ложным.
Блок-схема.

Цикл for является наиболее распространённым циклом в программировании, поэтому его следует изучить. Цикл for проводит инициализацию перед первым шагом цикла. Затем выполняется проверка условия цикла, и в конце каждой итерации происходит изменение управляющей переменной. Выглядит следующим образом:
for(инициализация; логическое выражение (условие); шаг (итерация))
команда
Любое из трёх выражений цикла (инициализация, логическое выражение или шаг) можно пропустить. Перед выполнением каждого шага цикла проверяется условие цикла. Если условие окажется ложным, то выполнение продолжится с инструкции, следующей за конструкцией for.
Помните, что выражение инициализации выполняется один раз, затем вычисляется условие, которое должно быть булевым выражением.
Как правило, цикл for используют для перебора. В качестве имени первой переменной часто используют i (сокр. от init), но вы можете использовать любое имя.
Простейший пример:
for (int x = 0; x < 9; x = x + 1)
mInfoTextView.append("\nЗначение x: " + x);

В этом примере переменной x присваивается начальное значение, равное нулю. Затем выполняется проверка условия в логическом выражении (x < 9), если результат проверки истинен, то выполняется оператор после выражения цикла. После чего процесс повторяется. Процесс продолжается до тех пор, пока результат проверки условия не станет ложным.
Третье выражение в цикле - шаг, то есть, на какое значение нужно изменить переменную. Строго говоря, в таком виде (x = x + 1) современные программисты не пишут, так как есть укороченная форма записи (x++). Предыдущий пример можно переписать по другому:
for (int x = 0; x < 9; x++)
Эта запись является классической и правильной, если нам нужно посчитать от 0 до 8. Может возникнуть соблазн написать, например, так:
for (int x = 0; x <= 8; x++)
Результат будет таким же, но такой код нежелателен. Старайтесь писать традиционно. Особенно это проявляется при работе с массивами.
Увеличение значения переменной на единицу - весьма распространённый случай. Но это не является обязательным условием цикла, вы можете установить шаг и с помощью умножения, вычитания и других действий. Например, мы хотим вывести процесс уменьшения жизней у очень любопытной кошки:
for (int life = 9; life >= 0; life--)
mInfoTextView.append("\nУ кошки осталось жизней: " + life);

Попробуйте потренироваться на кошках. Например, выводим чётные числа.
for (int x = 0; x < 9; x += 2)
mInfoTextView.append(" " + x); // между кавычками пробел
Получим:
0 2 4 6 8
Если нужно выполнить несколько операторов в цикле, то используют фигурные скобки.
for (int kitten = 1; kitten < 10; kitten++) {
mInfoTextView.append("\nСчитаем котят: " + kitten);
mResultEditText.setText("Ура! Нас подсчитали");
}
В этом примере выполняется цикл с выводом числа подсчитанных котят, а также выводится текст в текстовом поле. Кстати, это один из примеров неправильного кода, когда в текстовом поле девять раз подряд выводится одна и та же строка. Мы этого не замечаем, но в реальности процессор выполняет лишнюю работу и второй оператор безусловно нужно вынести за пределы блока кода, который относится к циклу. Подобные ошибки очень часто встречаются у начинающих программистов, которые забывают, как работает цикл.
Когда мы объявляем переменную в первой части оператора for(int i = 0; ...), то область видимости переменной ограничена телом цикла и эта переменная не доступна на другом участке кода. Это подходящий вариант, если переменная больше нигде не используется. При этом переменная имеет область видимости и продолжительность существования, совпадающие с видимостью и продолжительностью жизни самого цикла. Вне цикла переменная прекратит своё существование.
Если управляющую переменную цикла нужно использовать в других частях приложения, то её не следует объявлять внутри цикла.
int i; // эта переменная нам понадобится не только в цикле
for(i = 0; i < 10; i++){
// что-то делаем
}
// можем использовать переменную где-то ещё
x = i + 10;
С другой стороны, если видимость переменной ограничена в пределах цикла, то не будет никакого конфликта, если вы будете использовать одинаковые имена переменных в разных циклах for, так как они не будут друг другу мешать.
Иногда требуется указать несколько переменных в инициализационной части цикла. Для начала посмотрим на стандартный пример:
int a, b;
b = 4;
for(a = 1; a < b; a++) {
mInfoTextView.append("a = " + a + "\n");
mInfoTextView.append("b = " + b + "\n");
b--;
}
В данном цикле используются две переменные. Можно включить обе переменные в оператор for, чтобы не выполнять обработку второй переменной вручную:
int a, b;
for(a = 1, b = 4; a < b; a++, b--) {
mInfoTextView.append("a = " + a + "\n");
mInfoTextView.append("b = " + b + "\n");
}
Как видно из кода, запятая служит разделителем для двух переменных. Теперь оба разделённых запятой оператора в итерационной части цикла выполняются при каждом выполнении цикла. Данный код считается более эффективным, хотя на практике встречается редко.
Части цикла могут быть пустыми.
Оставим пустым первое выражение.
int i = 0;
for(; i < 10; i++){
// что-то делаем
mInfoTextView.append("\n" + i);
}
В следующем примере нет инициализационного и итерационного выражения:
int i;
boolean kind = false;
i = 0;
for( ; !kind; ) {
mInfoTextView.append("i равно " + i + "\n");
if(i == 10) done = true;
i++;
}
А можно вообще все три части оператора оставить пустыми:
for( ; ;) {
//...
}
В этом случае создаётся бесконечный цикл, который никогда не завершится. Практического смысла данный код не имеет.
С обычными числами обычно не работают в цикле for. Гораздо чаще цикл используют при работе с массивами.
Основная разница между ними, что массив может состоять из неупорядоченных чисел, а число элементов может быть разным. К счастью, у массива есть специальное свойство length - длина массива. Первый пример можно переписать следующим образом.
int[] mice = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (int i = 0; i < mice.length; i++)
mInfoTextView.append(" " + mice[i]);
Мы создали массив из чисел от 0 до 9. Затем проходим в цикле, но на этот раз во втором операторе не используем число 9, а вычисляем длину массива. Такой гибкий подход позволят проделывать с массивами разные трюки - упорядочивать, сортировать, переворачивать и т.д.
Например, если мы хотим вывести числа в обратном порядке, меняем логику следующим образом. Теперь нам нужно начинать вывод не с 0, а с 9, т.е. int i = 9 или int i = mice.length - 1 (для универсальности). Шаг будет не увеличиваться, а уменьшаться, значит - i--. А условием станет достижение 0, т.е. i >= 0. Проверяем.
int[] mice = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (int i = mice.length - 1; i >= 0; i--) {
mInfoTextView.append(" " + mice[i]);
}
Во многих языках существует более компактная форма for для перебора элементов массивов - foreach. Конструкция foreach не требует ручного изменения переменной-шага для перебора - цикл автоматически выполняет эту работу.
В Java решили не добавлять новое ключевое слово, а просто сделали усовершенствованный вид цикла for, который имеет вид:
for(тип итер_пер : коллекция) блок_операторов
Для сравнения напишем цикл для вычисления суммы значений элементов массива традиционным способом:
int[] nums = { 1, 2, 3, 4, 5 };
int sum = 0;
for(int i = 0; i < 5; i++) sum += nums[i];
Этот код можно переписать следующим образом:
int[] nums = { 1, 2, 3, 4, 5 };
int sum = 0;
for(int i : nums) sum += i;
При прохождении цикла переменной i автоматически присваивается значение, равное значению следующего элемента массива nums. Таким образом, при первом прохождении переменная i содержит значение 1, при втором - 2 и т.д. Кроме того при таком способе исключается возможность ошибок выхода за пределы массива.
Для этого способа можно использовать массив или любой класс с интерфейсом Iterable.
Можно прервать выполнение цикла с помощью оператора break:
int[] nums = { 1, 2, 3, 4, 5 };
int sum = 0;
for(int i : nums) {
sum += i;
if(i == 3) break; // останавливаем цикл, если значение равно 3
}
Учтите, что в цикле в стиле foreach итерационная переменная доступна только для чтения, так как она связана только с исходным массивом. Даже если вы измените её значение, то это не повлияет на работу с массивом.
Также можно использовать данный способ для многомерных массивов.
Поскольку каждый оператор for в стиле foreach перебирает элементы массива последовательно, начиная с первого и заканчивая последним, то данный способ удобен для многих операций. Например, для поиска значения в неупорядоченном массиве. Поиск прекращается после обнаружения нужного значения.
int[] nums = { 3, 1, 6, 4, 9, 5, 8, 2 };
int val = 5;
boolean found = false;
// ищем значение 5 в массиве
for (int x : nums) {
if (x == val) {
found = true;
break;
}
}
if (found) {
mInfoTextView.setText("Значение найдено");
}
Так как у нас неупорядоченный список, то нам нужно последовательно пройтись по всем элементам. Если нам повезёт и нужное значение встретится при переборе, то выходим из цикла и идём спать.
Также допустимо использование вложенных циклов, когда один цикл выполняется внутри другого:
int i, j;
for (i = 0; i < 10; i++) {
for (j = i; j < 10; j++) {
mInfoTextView.append("*");
}
mInfoTextView.append("\n");
}
В результате получим:
********** ********* ******** ******* ****** ***** **** *** ** *
При вложенных циклах количество повторений перемножается. В предыдущем примере было 100 повторений. Например, можно написать таблицу умножения.
int i, j, a = 0;
for (i = 1; i < 10; i++) {
for (j = 1; j < 10; j++) {
a = i * j;
System.out.print(a + " | ");
}
System.out.println();
}
Результат смотрите в вкладке LogCat.
Цикл for является более удобным вариантом цикла while.
for(int i = 10; i > 0; i--){
System.out.println("Отсчёт пошёл... " + i);
}
Этот же вариант с while:
int i = 10;
while(i > 0){
System.out.println("Отсчёт пошёл... " + i);
i--;
}
С помощью цикла можно рисовать красивые узоры, меняя координаты одной фигуры.
Составьте "Треугольник Флойда", который выглядит как набор чисел, которые увеличиваются на единицу. Например, треугольник с высотой шесть строк выглядит следующим образом.
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
16 17 18 19 20 21