Home Kotlin - 배열 및 컬렉션
Post
Cancel

Kotlin - 배열 및 컬렉션

배열 및 컬렉션

배열

배열은 프로덕션에서 잘 사용하지 않는다. 컬렉션을 주로 사용하기 때문이다. Effective Java에서도 배열의 사용보다 리스트의 사용을 권장하고 있다.

그러나 문법은 우선 알아둘 필요가 있다.

코틀린에서는 배열을 어떻게 표현할까?

1
2
3
4
5
6
7
8
9
10
11
12
13
fun main() {
	val array = arrayOf(100, 200)

	array.plus(300)

	for (i in array.indices) {
		println("${i} ${array[i]}")
	}

	for ((idx, value) in array.withIndex()) {
		println("$idx $value")
	}
}
  • array.plus()
    • 값을 쉽게 넣을 수 있다.
    • 자바에서 이를 구현하려면 배열을 복사하는 과정이 필요할 것이다.
  • array.indices
    • 0부터 마지막 index까지의 Range
  • array.withIndex()
    • 인덱스와 값을 한 번에 가져올 수 있다.

Kotlin Collection

컬렉션을 만들어줄 때 불변인지, 가변인지 설정해야 한다.

  • 가변(Mutable) 컬렉션
    • 컬렉션에 element를 추가 및 삭제할 수 있다.
  • 불변 컬렉션
    • 컬렉션에 element를 추가 및 삭제할 수 없다.

자바에서는 Collections.unmodifiableList()와 같다.

따라서 마찬가지로 불변 컬렉션이라 하더라도 Reference Type인 Element의 필드는 바꿀 수 있다는 점을 주의해야 한다.

다만 코틀린에서는 불변/가변을 반드시 지정해주어야 한다는 점이 다른 것이다.

List

기본

1
final List<Integer> numbers = Arrays.toList(100, 200);
1
2
val numbers = listOf(100, 200)
val emptyList = emptyList<Int>()
  • listOf() 를 통해 불변 리스트를 만들 수 있다.
  • 빈 리스트를 만들기 위해서는 emptyList를 이용하며 타입을 표기해주어야 한다.

단 타입을 추론할 수 있는 경우는 타입을 생략 가능하다. 아래 예시를 보자.

1
2
3
4
val numbers = listOf(100, 200)
printNumbers(emptyList())

private fun printNumbers(numbers: List<Int>) { }

위와 같이 타입을 추론할 수 있는 경우 생략이 가능하다.

값 가져오기

1
2
3
4
5
6
7
8
9
10
11
12
val numbers = listOf(100, 200)

numbers.get(0)
numbers[0]

for (number in numbers) {
	println(number)
}

for ((idx, value) in numbers.withIndex()) {
	println("$idx, $value")
}
  • 자바와 마찬가지로 get() 을 이용해 가져올 수 있다.
  • 배열처럼 가져올 수 있다.
  • withIndex() 사용이 가능하다.

가변 리스트 생성 방법

1
2
val numbers = mutableListOf(100, 200)
numbers.add(300)
  • 자바에 존재하는 리스트 기능들이 다 포함되어 있다.
  • 기본 구현체는 ArrayList 이다.

우선 불변 리스트로 만들고 반드시 필요한 경우에 가변 리스트로 바꾸는 방식으로 개발하는 것을 권장한다.

Set

Set은 List와 다르게 순서가 없고 중복된 Element는 존재할 수 없다.

이러한 자료구조적 의미만 제외하면 모든 기능이 List와 유사하다.

1
2
3
4
5
6
7
8
9
10
val numberSet = setOf(100, 200)
val numberMutableSet = mutableSetOf(100, 200)

for (number in numbers) {
	println(number)
}

for ((index, number) in numbers.withIndex()) {
	println("$index $number")
}
  • 기본 구현체는 LinkedHashSet 이다.

Map

우선 자바에서 맵을 다루는 방법을 보자.

1
2
3
4
5
Map<Integer, String> map = new HashMap<>();
map.put(1, "Monday");
map.put(2, "Tuesday");

Map.of(1, "Monday", 2, "Tuesday");

위의 자바 코드를 코틀린으로 바꿔보자.

1
2
3
4
5
6
val oldMap = mutableMapOf<Int, String>()
oldMap.put(1, "Monday")

oldMap[1] = "Monday"

mapOf(1 to "Monday", 2 to "Tuesday") //불변 map
  • 타입을 추론할 수 없기 때문에 타입을 표시해주었다.
  • 가변 Map이기 때문에 (key, value)를 넣을 수 있다.
  • 자바와 같이 put을 쓸 수도 있고 배열처럼 사용할 수도 있다.
  • mapOf(key to value)를 사용해 불변 Map을 만들 수 있다.

Map 값 사용

1
2
3
4
5
6
7
8
9
for (key in oldMap.keys) {
	println(key)
	println(oldMap[key])
}

for ((key, value) in oldMap.entries) {
	println(key)
	println(value)
}
  • keys를 이용해 key값을 이용할 수 있다.
    • 마찬가지로 get을 사용해도 되고 배열형식으로 사용할 수도 있다.
  • entries
    • key와 value를 한 번에 가져올 수 있다.

컬렉션의 null 가능성 / 자바와 함께 사용하기

1
2
3
4
5
6
7
8
List<Int?> : 
리스트에 null 들어갈  있지만, 리스트는 절대 null 아니다.

List<Int>? : 
리스트의 요소에는 null 들어갈  없지만 리스트는 null  있다.

List<Int?>? :
리스트에 null 들어갈 수도 있고, 리스트 자체가 null 수도 있다.
  • 위와 같이 ? 위치에 따라 null 가능성 의미가 달라지므로 차이를 잘 이해하고 주의해서 사용해야 한다.

자바와 함께 사용할 때 주의점

  • 자바는 읽기 전용 컬렉션과 변경 가능 컬렉션을 구분하지 않는다.

예를 들어 코틀린에서 불변 리스트를 만들어 사용하고 있다고 가정하자. (listOf)

자바에서 코틀린에서 해당 리스트를 가져오는데 이 때 자바는 불변 리스트인지 구분하지 않는다.

따라서 자바에서 Element를 추가하고 코틀린에서 해당 컬렉션을 다시 가져오면 오동작을 일으킬 수 있다.

  • 자바는 nullable 타입과 non-nullable 타입을 구분하지 않는다.

코틀린의 non-nullable 리스트를 자바에서 가져다 쓴다고 가정하자.

그리고 null을 해당 리스트에 추가하고 코틀린이 그 리스트를 다시 가져와 쓰면 오류가 발생할 수 있다.

※ 이러한 경우들을 방지하기 위해서는 코틀린 쪽의 컬렉션이 자바에서 호출될 수 있는 상황이라면 그 부분을 감안하여 다시 컬렉션이 돌아왔을 때의 방어 로직을 짠다거나 코틀린에서 Collections.unmodifiable를 사용하여 변경 자체를 방지하는 방법으로 해결할 수 있다.

  • 코틀린에서 자바 컬렉션을 가져다 사용할 때 플랫폼 타입을 신경써야 한다.
1
List<Integer>

위와 같은 컬렉션을 코틀린에서 가져다 쓴다고 가정해보자.

코틀린 입장에서는 아래의 경우들중 어떤 경우인지 판단할 수 없다.

1
2
3
List<Int?>
List<Int>?
List<Int?>?

이런 경우 자바 코드를 보며 맥락을 확인하고, 자바 코드를 가져오는 지점을 wrapping하여 처리해야 한다.

정리

  • 배열의 사용법이 약간 다르다.
  • 코틀린에서는 컬렉션 생성 시 불변/가변을 반드시 지정해야 한다.
  • List, Set, Map에 대한 사용법이 일부 다르다.
  • Java에서 Kotlin 코드를 섞어 컬렉션을 사용할 때에는 주의해야 한다.
    • Java에서 Kotlin
      • 불변 컬렉션의 수정 가능성
      • non-nullable 컬렉션에 null값 가능성
    • Kotlin에서 Java
      • 플랫폼 타입을 주의해야 한다.
This post is licensed under CC BY 4.0 by the author.