W3docs

Вложенные циклы в 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
101001,000
10010,0001,000,000
1,0001,000,0001,000,000,000

Если вложенный цикл работает с большим набором данных, спросите себя, действительно ли нужен внутренний цикл. Поиск через HashMap зачастую заменяет внутренний цикл-поиск и меняет O(n²) на O(n).

break и continue действуют только на внутренний цикл

Как мы видели в разделах break и continue: без метки оба оператора применяются только к самому внутреннему циклу. Чтобы выйти из внешнего цикла или пропустить его итерацию изнутри внутреннего, используйте break или continue с меткой — см. именованные операторы.

Разобранный пример

java— editable, runs on the server

Что дальше

Когда нужно выполнить break или continue для внешнего цикла из внутреннего, именованные операторы предоставляют для этого удобный способ.

Практика

Практика
Сколько раз выполнится System.out.println в: for (int i = 0; i < 4; i++) for (int j = 0; j < 3; j++) System.out.println(i+','+j);
Сколько раз выполнится System.out.println в: for (int i = 0; i < 4; i++) for (int j = 0; j < 3; j++) System.out.println(i+','+j);
Was this page helpful?