Вложенные циклы в Java
Вложенные циклы в Java для обработки многомерных данных: матрицы, сетки и шаблоны.
Вложенный цикл — это цикл внутри другого цикла. Внутренний цикл выполняется полностью при каждой итерации внешнего, поэтому тело исполняется внешний × внутренний раз. Это базовая конструкция для всех задач, связанных со строками и столбцами, парами или многомерными данными.
В этой главе предполагается, что вы знакомы с основными формами циклов — for-циклом и while-циклом. Любой цикл может быть вложен в любой другой; в примерах ниже используется for как наиболее распространённый вариант, но правило то же самое для while и for-each.
Два цикла for
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
System.out.println(i + "," + j);
}
}Вывод:
1,1
1,2
1,3
2,1
2,2
2,3
3,1
3,2
3,3При каждом значении i внутренний цикл проходит по j от 1 до 3, прежде чем i увеличивается. Обратите внимание, что j заново инициализируется значением 1 при каждом проходе внешнего цикла — внутренний цикл начинается заново при каждом повторении внешнего. Используйте различные переменные цикла (i и j здесь); использование одного и того же имени в обоих циклах — распространённый источник ошибок.
Обход двумерного массива
Классическое применение вложенных циклов — итерация по матрице:
int[][] grid = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
System.out.print(grid[r][c] + " ");
}
System.out.println();
}Каждая строка сетки сама является массивом; внешний цикл перебирает строки, внутренний — ячейки в каждой строке. Форма for-each ещё чище, когда индексы не нужны:
for (int[] row : grid) {
for (int cell : row) {
System.out.print(cell + " ");
}
System.out.println();
}Вывод шаблонов
Вложенные циклы — классическое упражнение для вывода шаблонов. Треугольник из звёздочек:
int rows = 5;
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= i; j++) {
System.out.print("*");
}
System.out.println();
}Вывод:
*
**
***
****
*****Счётчик внутреннего цикла зависит от переменной внешнего цикла — мощный шаблон, встречающийся постоянно.
Следите за сложностью
Один цикл по n элементам выполняется n раз. Цикл, вложенный в него, выполняется n × n = n² раз. Три вложенных цикла — n³ раз. При малом n это не имеет значения; при большом n — имеет очень большое:
| n | n² | n³ |
|---|---|---|
| 10 | 100 | 1,000 |
| 100 | 10,000 | 1,000,000 |
| 1,000 | 1,000,000 | 1,000,000,000 |
Если вложенный цикл работает с большим набором данных, спросите себя, действительно ли нужен внутренний цикл. Поиск через HashMap зачастую заменяет внутренний цикл-поиск и меняет O(n²) на O(n).
break и continue действуют только на внутренний цикл
Как мы видели в разделах break и continue: без метки оба оператора применяются только к самому внутреннему циклу. Чтобы выйти из внешнего цикла или пропустить его итерацию изнутри внутреннего, используйте break или continue с меткой — см. именованные операторы.
Разобранный пример
Что дальше
Когда нужно выполнить break или continue для внешнего цикла из внутреннего, именованные операторы предоставляют для этого удобный способ.