Цикл While в Java

Статья из группы Java Developer

Введение

Наши самые первые программы представляли собой последовательность инструкций, которые выполняются одна за другой. Без развилок. Это и HelloWorld, выводящий в консоль фразу приветствия, арифметические вычисления. Оператор while - 1После первых программ мы научились ветвлению, то есть программа выполняла те или иные действия в зависимости от условий. Вот как можно было бы закодировать включение кондиционера на обогрев и охлаждение:

if (tempRoom>tempComfort)
    airConditionerOn();
if (tempRoom<tempComfort
    heaterOn();
Сделаем следующий шаг. В быту мы часто выполняем однообразные повторяющиеся действия, например, чистим яблоки для пирога. Этот увлекательный процесс можно описать как:
  1. Если в тазике есть яблоки, то выполняем шаги с 1.1 по 1.4:

    1. 1.1. Берём яблоко
    2. 1.2. Чистим и нарезаем его дольками
    3. 1.3. Помещаем на основание пирога из теста на сковороде
    4. 1.4. Возвращаемся на шаг 1.
Оператор while - 2
Допустим у вас 10 яблок, 2 руки и один нож. В жизни вы последовательно чистите весь десяток, руководствуясь одним и тем же алгоритмом. А как заставить программу делать повторяющееся действие с каждым яблоком?
  • Привяжем себя к числу яблок,но если у нас их мало – часть команд выполнялось бы вхолостую без «полезной нагрузки» (и, возможно, порезались, очищая кожуру несуществующего яблока).
  • Если яблок больше, чем наших команд обработки – часть продуктов пропала бы необработанной.
  • Подобный «код» тяжело читать, в нём много повторов, его трудно модифицировать.

Циклы – операторы многократного выполнения действий

Цикл while Java (цикл вайл) хорошо подойдёт в нашем случае. Эта конструкция оформляет многократные действия в лаконичную и понятную структуру. Алгоритм по нарезке яблок для пирога в виде while в Java мог бы выглядеть как:

while(числоЯблокВТазике>0) {
    яблоко = тазик.взятьОчередноеЯблоко();
    положитьВПирог(яблоко.чистить().нарезать());
    числоЯблокВТазике--;//-- это декремент, уменьшает количество яблок на единицу
}
System.out.println('Яблоки для пирога обработаны.');

Синтаксис команды

Первый способ описания оператора while следующий:

while(Логическое выражение) {
	// Тело цикла - периодически выполняемые оператор(ы)
}
Выполняется следующим образом (по шагам):
  1. Вычисляем Логическое условие, следующее в скобках за while.
  2. Если логическое условие истинно, то выполняются операторы в теле цикла, после выполнения последнего оператора в теле цикла, переходим на шаг 1
  3. Если логическое условие ложно, то переходим к первому оператору за пределами цикла while.

Цикл с предусловием

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

public static void main(String[] args) {
    int number = 3; // Возводимое в степень число
    int result = 1; // Результат возведения в степень
    int power = 1; // Начальный показатель степени
    while(power <= 10) { // условие входа в цикл
        result = result * number;
        System.out.println(number + " в степени " + power + " = " + result);
        power++;
    }
}
Результат вывода на консоль:

3 в степени 1 = 3
3 в степени 2 = 9
3 в степени 3 = 27
3 в степени 4 = 81
3 в степени 5 = 243
3 в степени 6 = 729
3 в степени 7 = 2187
3 в степени 8 = 6561
3 в степени 9 = 19683
3 в степени 10 = 59049
Process finished with exit code 0

Цикл с постусловием

Второй вид цикла:

do {
    // Тело цикла - периодически выполняемые оператор(ы)
}while (Логическое выражение);
Выполняется следующим образом (шаги):
  1. Выполняется тело цикла (сразу после ключевого слова do).
  2. Вычисляем Логическое условие, следующее в скобках за while.
  3. Если логическое условие истинно, то переходим на шаг 1
  4. Если логическое условие ложно, то переходим к первому оператору за пределами цикла while.
Два основных отличия от предыдущего вида цикла: тело цикла как минимум выполняется один раз и логическое условие проверяется после выполнения тела цикла. Поэтому этот вид цикла while называют циклом с постусловием. На этот раз выведем таблицу степеней числа, не превышающую 10000:

public static void main(String[] args) {
    int number = 3;// Возводимое в степень число
    int result = number;// Результат возведения в степень
    int power = 1;// Начальный показатель степени
    do {
        System.out.println(number + " в степени " + power + " = " + result);
        power++;
        result = result * number;
    }while (result < 10000); // условие выхода из цикла
Результат вывода на консоль:

3 в степени 1 = 3
3 в степени 2 = 9
3 в степени 3 = 27
3 в степени 4 = 81
3 в степени 5 = 243
3 в степени 6 = 729
3 в степени 7 = 2187
3 в степени 8 = 6561
Process finished with exit code 0
Обратите внимания на изменения в коде, сравнив с вариантом цикла с предусловием.

Интересные факты о работе с циклами

Управляющие команды в теле цикла

Существуют две команды, влияющие на ход выполнения цикла: break, особенности применения которого мы покажем в следующей главе, и continue.
  • continue – прекращает выполнение тела текущего цикла и осуществляет переход к логическому выражению оператора while. Если вычисленное выражение будет истинно – выполнение цикла будет продолжено.
  • break – немедленно прекращает выполнение текущего цикла и осуществляет переход к первой команде за его пределами. Таким образом, выполнение текущего цикла прерывается. Подробнее мы рассмотрим её в следующей теме.
Вспомним про наш фруктовый пример. Если мы не уверены в качестве предложенных яблок, то могли бы изменить код с применением команды continue:

while(числоЯблокВТазике>0) {
    яблоко = тазик.взятьОчередноеЯблоко();
    числоЯблокВТазике--;//-- это декремент, уменьшает количество яблок на единицу
    if (яблоко.плохое()) {  // метод вернет true для гнилого и т.п. яблока
        яблоко.выкинутьВМусор();
        continue; // продолжим цикл, перейдем к условию числоЯблокВТазике>0
    }
    положитьВПирог(яблоко.чистить().нарезать());
}
Конструкцию continue часто применяют, когда в теле цикла необходимо выполнять команды при наступлении некоторого условия, например, выполнить действия при срабатывании датчика в оборудовании (а иначе просто продолжить цикл считывания его показателей) или вычислить выражение только на определенных шагах цикла. Пример для последнего случая – вычисление в цикле while суммы кубов натуральных чисел, у которых квадрат меньше их количества:

public static void main(String[] args) {
    int sum = 0;    // итоговая сумма
    int i = 0;      // стартовое число ряда
    int count = 20; // количество чисел
    while(i<=count) {
        i++;        // берем очередное число, i++ эквивалентно i=i+1
        if (i*i<=count)  // если квадрат числа меньше
            continue;   // количества чисел - сумму не считаем
                        // переходим к следующему числу в цикле
        sum += i*i*i; // иначе считаем сумму кубов чисел
    } // sum += i*i*i - форма записи, аналогичная sum = sum + i*i*i
    System.out.println(sum);// печатаем результат
}

Бесконечный цикл

Данные управляющие команды чаще всего находят применение в бесконечном цикле. Его так называют, потому что логическое условие выхода никогда не выполняется. В коде он выглядит примерно как:

while(true) {
    // Тело цикла 
}
В этом случае и пригодится применение команды break для организации выхода из него. Этот вид цикла имеет место при ожидании внешних условий, которые формируются за пределами логики тела цикла. Например, в играх, эмулирующих виртуальный мир вокруг героя (выход из цикла = выход из игры), операционных системах. Или при использовании алгоритмов, возможно, улучшающих результат с каждым последующим вызовом в цикле, но ограничивая их по времени или наступлению внешнего события (шашки, шахматы или предсказание погоды). Следует помнить, что в обычных условиях бесконечные циклы – одна из проблем неустойчивости программы. Для демонстрации вернёмся к степеням числа:

public static void main(String[] args) {
    int number = 3; // Возводимое в степень число
    int result = 1; // Результат возведения в степень
    int power = 1; // Начальный показатель степени
    while(true) {
        result = result * number;
        System.out.println(number + " в степени " + power + " = " + result);
        power++;
        if (power>10)
            break; // выход из цикла
    }
}
Результат вывода на консоль:

3 в степени 1 = 3
3 в степени 2 = 9
3 в степени 3 = 27
3 в степени 4 = 81
3 в степени 5 = 243
3 в степени 6 = 729
3 в степени 7 = 2187
3 в степени 8 = 6561
3 в степени 9 = 19683
3 в степени 10 = 59049
Process finished with exit code 0

Вложенные циклы

Вот мы и подошли к завершающей теме о наших циклах. Вспомним о яблочном пироге (надеюсь, вы не голодны в данный момент) и наш «цикл»:
  1. Если в тазике есть яблоки, выполняем шаги с 1.1 по 1.4:

    1. 1.1. Берем яблоко
    2. 1.2. Чистим и нарезаем его дольками
    3. 1.3. Помещаем на основание пирога из теста на сковороде
    4. 1.4. Возвращаемся на шаг 1.
Подробнее распишем процесс нарезания дольками:
  1. Число долек = 0
  2. Пока число долек < 12, выполнить шаги с 2.1 по 2.3

    1. 2.1. Отрезать очередную дольку от яблока
    2. 2.2. Кол-во долек ++
    3. 2.3. Возвращаемся на шаг 2
И вставим в наш кондитерский алгоритм:
  1. Если в тазике есть яблоки, то выполняем шаги с 1.1 по 1.6:

    1. 1.1. Берем яблоко
    2. 1.2. Очищаем его от кожуры
    3. 1.3. Число долек = 0
    4. 1.4. Пока число долек < 12, выполнить шаги с 1.4.1 по 1.4.3
      1. 1.4.1. Отрезать очередную дольку от яблока
      2. 1.4.2. Кол-во долек ++
      3. 1.4.3. Возвращаемся на шаг 1.4
    5. 1.5. Помещаем дольки на тестовое основание пирога из теста на сковороде
    6. 1.6. Возвращаемся на шаг 1.
Получили цикл в цикле. Подобные конструкции весьма частые. Для завершающего примера построим таблицу умножения, которые школьники 90-х видели на обложках тетрадей в младших классах.
Оператор while - 3

 public static void main(String[] args) {
    // Выводим значения второго множителя в строке
    System.out.println("    2  3  4  5  6  7  8  9"); 
    int i = 2;      // первый множитель, присваиваем стартовое значение
    while(i<10) {   // Первый цикл, выполняем пока первый множитель меньше 10
        System.out.print(i + " | ");// Выводим первый множитель в начало строки
        int j = 2;                  // второй множитель, стартовое значение
        while (j<10) { // Второй цикл, выполняем пока второй множитель меньше 10
            int mul=i*j; // Считаем произведение множителей
            if (mul<10)  // Если содержит одну цифру-после него выводим два пробела
                System.out.print(mul + "  ");
            else   // иначе выводим произведение и после него - один пробел
                System.out.print(mul + " ");
            j++;     // Увеличиваем на единицу второй множитель,
        }            // Переходим к началу второго цикла (while (j<10 ).... )
        System.out.println(); // Перейдем на следующую строку вывода
        i++;                  // Увеличиваем на единицу первый множитель,
    }                         // Перейдем к началу первого цикла (while ( i<10 ) ....
}
Результат вывода на консоль:

     2  3  4  5  6  7  8  9
2 | 4 6 8 10 12 14 16 18
3 | 6 9 12 15 18 21 24 27
4 | 8 12 16 20 24 28 32 36
5 | 10 15 20 25 30 35 40 45
6 | 12 18 24 30 36 42 48 54
7 | 14 21 28 35 42 49 56 63
8 | 16 24 32 40 48 56 64 72
9 | 18 27 36 45 54 63 72 81
Process finished with exit code 0
Циклы (в частности, оператор while) – один из фундаментальных кирпичиков построения программ. Решая задачи на JavaRush, вы изучите все их разнообразие, разберёте тонкости функционирования и получите практические навыки их применения.
Комментарии (83)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Alesster Уровень 16, San Sebastian, Spain
25 мая 2022
В задаче на "вычисление в цикле while суммы кубов натуральных чисел, у которых квадрат меньше их количества:" кажется опечатка. Сам код считает сумму кубов натуральных чисел, у которых квадрат больше их количества. Не так?
Павел Хвостов Уровень 6, Москва, Россия
4 февраля 2022
Мне знакомый дал задачку на цикл while: дана строка .......... (10 точек), пока строка не станет равной ... (3 точки) выводить эту строку и количество символов в ней в консоль. Никак не могу осилить, то ли гуглом плохо пользуюсь!! Я подозреваю нужно объявить переменную String,а как я не могу понять....
Pavel Mordovin Уровень 8, Санкт-Петербург, Россия
20 января 2022
Вот теперь то я её решууу, злодейку Таблица умножения Ӏ Java Syntax: 3 уровень, 6 лекция
Abilkair Bolatbayev Уровень 42, Алматы, Казахстан
19 января 2022
разжевали пережевали, невозможн не понять :-)
Alisher Уровень 27, Алматы, Kazakhstan
2 декабря 2021
Господи, в только что лет узнал что таблица умножения названа в честь Пифагора
Konstantin Уровень 28, Yekaterinburg, Россия
22 сентября 2021
очень крутая статья !!! спасибо!!
Dimsos Уровень 29, Краснодар, Russian Federation
13 сентября 2021
Я так понял в этом и аналогичных ему кодах ошибка. Должно быть result = power * number. Верно я понимаю? public static void main(String[] args) { int number = 3;// Возводимое в степень число int result = number;// Результат возведения в степень int power = 1;// Начальный показатель степени do { System.out.println(number + " в степени " + power + " = " + result); power++; result = result * number;
Victor Zav Уровень 22, Fort Lauderdale
19 июня 2021
– вычисление в цикле while суммы кубов натуральных чисел, у которых квадрат меньше их количества: Actual: while(i<=count) { i++; // берем очередное число, i++ эквивалентно i=i+1 if (i*i=<count) // если квадрат числа меньше Expected: while (i < count) { i++; // берем очередное число, i++ эквивалентно i=i+1 if (i * i < count) // если квадрат числа меньше 😎
Mike-L Уровень 43
8 июня 2021

for (int i = 1; i < 10; i++) {
    for (int j = 1; j < 10; j++) {
        System.out.print(i * j + "\t");
    }
    System.out.println();
}
используем \t и вуаля "Таблица умножения" в два захода for готова
Serbin Alexander Уровень 12, Москва, Россия
29 мая 2021
Сделал таблицу Пифагора через цикл for, с ним по проще вышло...

System.out.println("     2  3  4  5  6  7  8  9");
        for (int i = 2; i < 10; i++) {
            System.out.print(i + " | ");
            for (int j = 2; j < 10; j++) {
                int res = i * j;
                if (j < 10) {
                    System.out.print(" " + res + " ");
                } else {
                    System.out.println();
                }
            }
            System.out.println("");