JavaRush/Java блог/Java Developer/Цикл While в Java
Автор
Артем Divertitto
Senior Android-разработчик в United Tech

Цикл While в Java

Статья из группы Java Developer
участников

Введение

Наши самые первые программы представляли собой последовательность инструкций, которые выполняются одна за другой. Без развилок. Это и HelloWorld, выводящий в консоль фразу приветствия, арифметические вычисления. После первых программ мы научились ветвлению, то есть программа выполняла те или иные действия в зависимости от условий. Вот как можно было бы закодировать включение кондиционера на обогрев и охлаждение:
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, вы изучите все их разнообразие, разберёте тонкости функционирования и получите практические навыки их применения.
Комментарии (120)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Grigoryvvv
Уровень 6
Expert
21 января, 09:30
21.01.24. 4 уровень
Cat_Virus
Уровень 9
24 декабря 2023, 03:52
Мне кажется небольшая ошибка, там где считали сумму кубов натуральных чисел, квадрат которых меньше их количества. Посчитали кубы чисел, квадрат которых больше их количества. Нужно изменить условие задачи , или в условном операторе написать >=
Arbuzzik
Уровень 6
18 января, 19:56
Тоже заметил.
Максим Li Java Developer
4 декабря 2023, 04:42
+
Louis d'Ipinaisse
Уровень 14
Expert
29 октября 2023, 17:20
я школьник 00-х но тоже видел такие тетрадки)
Grigoryvvv
Уровень 6
Expert
21 января, 09:20
Да они до сих пор такие. Математика, она и в Африке математика. )
Roman Kibenko
Уровень 9
10 сентября 2023, 06:56
очень понятно, доступно и полезно!!! вам +100 к карме )
Lazarus#22242
Уровень 6
31 августа 2023, 10:56
Вот на яблоках всегда понятнее! Спасибо!
dim11981
Уровень 47
8 августа 2023, 09:36
do {
...
}while (result < 10000); // условие ПРОДОЛЖЕНИЯ цикла
из выражения внутри while понятно, когда придется вывалиться из цикла, но семантически это условие продолжения, а не выхода, иначе, присвоив result = 0 сразу выходим, а хотели в цикл)) но в некоторых других языках, действительно, может быть условием выхода.
aleksEy
Уровень 16
9 июня 2023, 08:37
Ну тогда делаем вывод таблицы в одну строчку :) System.out.printf( "____2__3__4__5__6__7__8__9_ \n2 | 4 6 8 10 12 14 16 18 \n3 | 6 9 12 15 18 21 24 27 \n4 | 8 12 16 20 24 28 32 36 \n5 | 10 15 20 25 30 35 40 45 \n6 | 12 18 24 30 36 42 48 54 \n7 | 14 21 28 35 42 49 56 63 \n8 | 16 24 32 40 48 56 64 72 \n9 | 18 27 36 45 54 63 72 81");
6 июля 2023, 18:03
что делает метод printf()?
26 июля 2023, 20:03
А если эту табличку нужно будет сделать не до 9, а, например, до 90?
Evgeny Makarov
Уровень 13
2 мая 2023, 16:40
<quote> Пример для последнего случая – вычисление в цикле 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);// печатаем результат } </quote> Мне одному кажется, что должно быть (i*i>=count) в условии оператора continue? 🤔
Andrew Potapenko
Уровень 15
21 мая 2023, 10:23
+ мне тоже
Артем
Уровень 6
16 июля 2023, 15:07
нууу похоже... ведь если квадрат больше - мы должны выполнить continue а если меньше - продолжать цикл т.е. считаем все в пределах 20. А если наоборот, то больше 20. ? 🤔
Anatoly Enterprise Java Developer
19 апреля 2023, 18:27
в принципе неплохо