Kotlin의 if와 java의 if는 어떻게 다른가? 예를들면 java와 Kotlin의 3항 연산자가 있다. 다음의 코드를 확인해보자.
if(a > b) a else b
a > b ? a : b
위 둘의 코드는 완전히 같은 의미를 갖고 있다. 하지만, Kotlin에서는 if가 값을 만들어 내기 때문에 Java와 달리 3항 연산자가 필요가 없다. 따라서 이런 특성을 활용하면 아래의 eval 함수에서 return문과 중괄호를 없애고 if 식을 본문에서 사용해 더 간단하게 만들 수 있다.
fun eval(e: Expr): Int =
if (e is Num) {
e.value
} else if (e is Sum) {
eval(e.right) + eval(e.left) }
else {
throw IllegalArgumentException("Unknown expression")
}
println(eval (Sum(Num(1), Num(2)))) // 3
위의 eval함수를 when을 사용하여 다음과 같이 바꿀 수 있다.
fun main(e: Expr): Int = when(e) {
is Num -> e.value
is Sum -> eval(e.right) + eval(e.left)
else -> throw IllegalArgumentException("Unknown expression")
}
무엇보다 코드의 양과 가독성이 정말 많이 올라가지 않았는가?
더 중요한 것은 타입을 검사하는 동안 스마트 캐스트
가 이뤄진다. 따라서 Num이나 Sum 멤버에 접근할 때 변수를 강제로 캐스팅할 필요가 없다. 그리고 무엇보다 만약에 조건에 따른 연산이 복잡해지면 블록을 사용해서 표현할 수 있다. 예들 들어서 아래의 코드는 필자가 BOJ에서 Two Pointer를 이용하여 풀었던 알고리즘 문제이다.
fun main() = with(Scanner(System.`in`)) {
...
while (right < n) {
when {
intArr[left] + 5 > intArr[right] -> {
right ++
cnt ++
}
else -> {
left ++
right ++
}
}
...
}
when 안에서 조건이 만족되면 블록을 활용하여 여러 연산을 진행할 수 있다.
while 과 for의 경우 자바 큰 차이를 갖고 있지 않다. 단지 kotlin 식 문법으로 a..b, until, upTo, step, downTo 등 명시할 내용을 알고 넘어가면 되겠다.
예제로 문자에 대한 2진 표현을 출력하는 프로그램을 작성해보자.
val binaryReps = TreeMap<Char, String>() // key에 대한 정렬이 필요할 때 TreeMap을 사용
for (c in 'A'..'F') {
val binary = Integer.toBinaryString(c.toInt()) // ASCII 코드를 2진 표현으로 바꾼다.
binary[c] = binary // c를 키로 c의 2진 표현을 맵에 넣는다.
}
for ((letter, binary) in binaryReps) { // 각 letter(key)에 대해 binary(value)를 이터레이션 한다.
println("$letter = $binary")
}
우선 자바에서는 Map을 사용하여 key와 value를 이용하게 되었을 때는 다음과 같은 코드로 해당 Map을 수정할 수 있다.
binary.put(c, binary)
하지만 코틀린에서는 binary[c] = binary
와 같이 보다 직관적인 방법으로 put을 수행할 수 있다. 위 예제의 TreeMap의 경우 key값을 기준으로 자동으로 정렬하고 싶을 때 사용하면 된다. 기본적으로 heap 구조를 가져가게 된다. 다음은 hashMapOf을 이용한 알고리즘 문제 풀이이다. 아래의 예제를 통해 확인해보자.
fun solution1(s: String): Int {
val dicNumber: HashMap<String, String>
dicNumber = hashMapOf(
"one" to "1",
"two" to "2",
"three" to "3",
"four" to "4",
"five" to "5",
"six" to "6",
"seven" to "7",
"eight" to "8",
"nine" to "9",
"zero" to "0"
)
...
}
여기서 key값에 따른 value값을 변경하고 싶으면 dicNumber["one"] = "하나"
과 같은 코드를 작성하면 된다.