1. 기본 중의 기본 — for 문
코틀린의 for문은 자바의 그것보다 훨씬 직관적이다.
컬렉션이나 배열을 순회할 때 가장 기본적으로 사용된다.
val list = listOf("a", "b", "c")
for (item in list) {
println(item)
}
인덱스가 필요할 땐
for (i in list.indices) {
println("index=$i, value=${list[i]}")
}
for ((index, value) in list.withIndex()) {
println("index=$index, value=$value")
}
withIndex()는 인덱스와 값을 동시에 다뤄야 할 때 가장 깔끔한 방식이다.
2. 범위를 이용한 반복 — 직관적이고 강력한 Range 문법
범위 연산자는 코틀린 반복문의 진가를 보여주는 부분이다.
for (i in 1..5) println(i) // 1,2,3,4,5 (포함)
for (i in 1 until 5) println(i) // 1,2,3,4 (5는 제외)
for (i in 5 downTo 1) println(i) // 5,4,3,2,1
for (i in 1..10 step 2) println(i) // 1,3,5,7,9
..: 양 끝 포함until: 마지막 값은 제외downTo: 감소 방향 반복step: 반복 간격 지정
범위를 이용하면 숫자 기반 루프를 간결하게 표현할 수 있다.
3. while / do-while — 조건 기반 반복의 정석
조건에 따라 반복을 제어해야 한다면 while 또는 do-while을 사용한다.
var i = 0
while (i < 3) {
println(i)
i++
}
do-while은 최소 한 번은 실행되어야 할 때 유용하다.
var j = 0
do {
println(j)
j++
} while (j < 3)
4. repeat — 단순 반복의 미니멀한 대안
“그냥 N번 반복하고 싶을 뿐인데 변수를 굳이 선언할 필요는 없다”
이럴 땐 repeat을 쓰면 된다.
repeat(3) { index ->
println("반복: $index")
}
짧고 깔끔하며, 단순 횟수 반복에 매우 적합하다.
5. 컬렉션 중심의 반복 — forEach와 forEachIndexed
코틀린답게 함수형 스타일로 반복을 처리할 수도 있다.
val list = listOf("A", "B", "C")
list.forEach { println(it) }
list.forEachIndexed { index, value ->
println("[$index] $value")
}
주의할 점
forEach 내부에서는 break나 continue를 직접 사용할 수 없다.
필요하다면 return@forEach 같은 **라벨 반환(label return)**을 사용하거나, 전통적인 for문으로 전환하자.
6. Sequence — 대용량 데이터 처리의 비밀 병기
여러 연산(filter, map, sorted)을 연달아 적용해야 하는 경우,
일반 컬렉션은 매번 새로운 리스트를 만들어 메모리를 낭비한다.
이럴 땐 **지연 평가(Lazy Evaluation)**를 지원하는 Sequence를 활용하자.
val seq = generateSequence(1) { it + 1 }
.take(1000)
.filter { it % 2 == 0 }
.map { it * 2 }
seq.forEach { println(it) }
Sequence는 연산을 필요할 때만 계산하므로, 대규모 데이터 처리에 유리하다.
7. 중첩 루프 제어 — 라벨의 활용
코틀린은 중첩 루프를 제어할 때 라벨(label) 문법을 지원한다.
한 줄로 바깥 루프까지 한방에 빠져나올 수 있다.
outer@ for (i in 1..3) {
for (j in 1..3) {
if (i == 2 && j == 2) break@outer
}
}
break@outer: 지정한 라벨의 루프를 즉시 종료continue@outer: 다음 반복으로 넘어감
8. 람다 내부 제어 — return의 오해
람다 안에서 return을 사용하면, 기본적으로 외부 함수 전체를 반환해버린다.
이를 방지하려면 return@forEach와 같은 명시적 라벨 반환을 써야 한다.
val numbers = listOf(1, 2, 3, 4)
numbers.forEach {
if (it == 3) return@forEach
println(it)
}
println("끝") // 정상 실행됨
9. 컬렉션 수정 시의 주의점
리스트를 순회하면서 동시에 수정하면 예기치 않은 에러가 발생할 수 있다.
이럴 땐 iterator를 이용하자.
val mutable = mutableListOf(1, 2, 3, 4)
val it = mutable.iterator()
while (it.hasNext()) {
if (it.next() % 2 == 0) it.remove()
}
println(mutable) // [1, 3]
답글 남기기