for와 중첩 반복
카운터의 초기화·조건·증가를 한곳에 모으고 중첩 반복의 총 실행 횟수와 for·while 선택 기준을 계산합니다.
while로 모든 반복을 표현할 수 있지만 반복 횟수를 세는 변수의 선언, 계속 조건, 증감이 멀리 떨어질 수 있습니다.
for는 이 세 요소를 머리 부분에 모아 범위를 보여 줍니다.
먼저 배열 없이 1부터 3까지 출력하며 문법을 익힌 뒤, 실행 인자를 순회하는 형태로 확장합니다.
가장 작은 for
다음 반복문은 회차 1, 2, 3을 차례로 출력합니다.
public class ForRange {
public static void main(String[] args) {
for (int session = 1; session <= 3; session++) {
System.out.println("session=" + session);
}
}
}session=1
session=2
session=3초기값은 1, 계속 조건은 session <= 3, 한 회차 뒤의 변화는 session++입니다.
배열의 0 기반 인덱스와 길이 경계는 ch3에서 배열을 만든 뒤 다룹니다.
for문의 실행 순서
for (int session = 1; session <= 3; session++) {
System.out.println(session);
}실행 순서는 다음과 같습니다.
int session = 1은 반복 전체에서 한 번 실행됩니다.session <= 3을 검사합니다. 거짓이면 반복을 끝냅니다.- 본문을 실행합니다.
session++를 실행합니다.- 2번 조건 검사로 돌아갑니다.
같은 뜻의 while은 카운터 선언이 반복문 밖에 남습니다.
int session = 1;
while (session <= 3) {
System.out.println(session);
session++;
}카운터가 반복 밖에서 필요 없다면 for가 스코프를 더 좁힙니다.
반대로 종료 시점이 사용자 명령이나 누적 합계처럼 본문 사건에 달려 있으면 while이 읽기 쉽습니다.
생략식과 무한 반복
for의 초기화, 조건, 증감은 각각 생략할 수 있습니다.
for (;;) {
// break가 없다면 계속 실행
}조건을 생략하면 항상 참으로 취급합니다.
while (true)와 같은 무한 반복입니다.
종료 조건이 본문 안의 여러 사건으로 표현될 때 사용할 수 있지만 break가 없거나 도달할 수 없으면 끝나지 않습니다.
다음 프로그램은 명시적인 한계에서 빠져나옵니다.
public final class ForWithBreak {
public static void main(String[] args) {
int sum = 0;
for (int number = 1; ; number++) {
sum += number;
if (sum >= 15) {
System.out.println("number=" + number);
break;
}
}
System.out.println("sum=" + sum);
}
}number=5
sum=15number 초기화와 증가는 for 머리에 있고, 합계라는 종료 사건은 본문에 있습니다.
조건 칸을 비운 이유를 break가 직접 보여 줍니다.
단순히 number <= 5처럼 상한을 알고 있다면 조건 칸에 쓰는 편이 낫습니다.
중첩 반복 횟수
Study Log의 2일치, 하루 3회 학습 슬롯을 출력합니다.
public final class StudyGrid {
public static void main(String[] args) {
int printed = 0;
for (int day = 1; day <= 2; day++) {
for (int session = 1; session <= 3; session++) {
printed++;
System.out.println("day=" + day + ", session=" + session);
}
}
System.out.println("printed=" + printed);
}
}day=1, session=1
day=1, session=2
day=1, session=3
day=2, session=1
day=2, session=2
day=2, session=3
printed=6바깥 반복 한 회마다 안쪽 반복이 처음부터 세 번 실행됩니다. 총 본문 횟수는 2 × 3 = 6입니다. 두 상한이 입력 크기라면 작업량도 곱으로 늘어납니다. 격자나 모든 조합이 실제 요구일 때만 중첩합니다.
안쪽에서 break하면 현재 day의 session 반복만 끝나고 다음 day로 넘어갑니다.
전체 반복을 끝내려면 바깥 상태를 함께 바꾸거나 메서드에서 return하는 구조를 고려합니다.
for 기반 일괄 처리
앞 절의 while 배치는 index가 항상 증가하는지 따로 확인해야 했습니다.
모든 토큰을 한 번씩 보는 현재 요구에는 향상된 for가 더 직접적입니다.
for (String token : args)는 args의 각 문자열을 앞에서부터 한 번씩 token에 넣는 향상된 for입니다.
ch1에서 args가 문자열 배열임을 확인했고, 배열의 생성과 인덱스는 다음 장에서 자세히 배웁니다.
여기서는 카운터가 필요 없는 “각 입력 한 번”의 표현으로 사용합니다.
public final class BatchFor {
public static void main(String[] args) {
int savedCount = 0;
int totalMinutes = 0;
for (String token : args) {
if (token.equals("quit")) {
break;
}
int separator = token.indexOf(':');
if (separator <= 0 || separator == token.length() - 1) {
System.out.println("skip=" + token);
continue;
}
String topic = token.substring(0, separator);
int minutes = Integer.parseInt(token.substring(separator + 1));
if (minutes < 1 || minutes > 600) {
System.out.println("skip=" + token);
continue;
}
savedCount++;
totalMinutes += minutes;
System.out.println("saved=" + topic);
}
System.out.println("count=" + savedCount + ", total=" + totalMinutes);
}
}saved=variables
skip=invalid
saved=conditions
count=2, total=75화면 번호나 이전 원소 위치가 필요하다면 인덱스 for를 사용합니다.
for와 while 선택
| 반복 요구 | 우선 선택 | 카운터 범위 |
|---|---|---|
| 0부터 배열 길이 전까지 | 인덱스 for | for 블록 내부 |
| 각 입력을 한 번씩 | 향상된 for | 카운터 없음 |
| 종료 명령까지 | while | 입력 상태에 따라 |
| 합계가 한계를 넘을 때까지 | while 또는 무한 for + break | 본문 사건에 따라 |
| 행×열 모든 조합 | 중첩 for | 각 블록에 별도 카운터 |
문법을 서로 변환할 수 있다는 사실보다 종료 조건이 어디에 가장 분명히 보이는지를 기준으로 삼습니다. 반복 변수의 수명을 좁힐 수 있다면 그것도 선택 근거입니다.
연습 문제
5일 동안 하루 3회의 슬롯을 중첩 for로 출력하세요.
단, 3일차 2회는 휴식이라 continue로 건너뛰고, 총 출력 회차 수를 마지막에 표시합니다.
해설 보기
public final class WeeklySlots {
public static void main(String[] args) {
int printed = 0;
for (int day = 1; day <= 5; day++) {
for (int session = 1; session <= 3; session++) {
if (day == 3 && session == 2) {
continue;
}
printed++;
System.out.println(day + "-" + session);
}
}
System.out.println("printed=" + printed);
}
}전체 조합은 15개이고 하나를 건너뛰므로 printed=14입니다.
continue는 안쪽 session 반복의 현재 회차만 끝내며 3일차 3회와 이후 날짜는 계속 실행됩니다.