코틀린(Kotlin)

코틀린(kotlin) : Collections : List, Set, Map

알통몬_ 2018. 2. 7. 11:30
반응형


공감 및 댓글은 포스팅 하는데

 아주아주 큰 힘이 됩니다!!

포스팅 내용이 찾아주신 분들께 

도움이 되길 바라며

더 깔끔하고 좋은 포스팅을 

만들어 나가겠습니다^^

 


이번 포스팅에서는 Collections : List, Set, Map 에 대해 공부합니다.


많은 프로그래밍 언어들과는 다르게, 코틀린에서는 

mutable 과 immutable 컬렉션(List, Set, Map)을 구분합니다.

컬렉션을 정확하게 edit 할 수 있으면 버그를 제거하고, 좋은 API를 설계하는데

유용합니다.


mutable collection의 read-only view와 immutable collection의 차이점을

이해하는 것이 중요합니다.

둘 다 쉽게 생성할 수 있지만, 이 둘의 차이에 대해 시스템에서는 알려주지 않기 때문에

이것의 추적은(관련이 있다면) 사용자에게 달려있습니다.


코틀린의 List<out T> 타입은 인터페이스이고, size, get 등등의 read-only operations을 

제공합니다. 자바에서처럼 List<..> 는 Collection<T>를 상속받고 이 Collection<T>는

Iterable<T>를 상속 받습니다.

리스트를 변경하는 메서드는 MutableList<T> 인터페이스에 의해서 추가되었습니다.

이러한 패턴은 Set<out T>/MutableSet<T>, Map<K, out V> / MutableMap<K, V>에도

동일하게 적용됩니다.


List 와 Set 타입의 기본적인 사용법에 대해 봅시다.

val numbers: MutableList<Int> = mutableListOf(1, 2, 3, 4, 5)
val readOnlyView: List<Int> = numbers
println(numbers) // prints "[1, 2, 3, 4, 5]"
numbers.add(6)
println(readOnlyView) // prints "[1, 2, 3, 4, 5, 6]"
readOnlyView.clear() // -> does not compile

val strings = hashSetOf("a", "b", "c", "c")
assert(strings.size == 3)


코틀린에서는 List 와 Set 만을 위한 문법은 따로 있지 않습니다.

대신에 표준 라이브러리에 있는 listOf(), mutableListOf(), setOf(), mutableSetOf() 메서드를

사용해서 List or Set 을 생성하면 됩니다.

성능이 중요한 코드가 아닌 Map은 간단한 관용구를 이용해서 생성할 수 있습니다.

예) mapOf(a to b, c to d)

fun main(args: Array<String>) {
val maps = mapOf(1 to "AAA", 2 to "BBB")
print(maps[1])
}


* read-only view 변수는 동일한 List를 가리키고 List가 변경되면 같이 변경됩니다.

아래 결과를 말합니다.

val numbers: MutableList<Int> = mutableListOf(1, 2, 3, 4, 5)
val readOnlyView: List<Int> = numbers
println(numbers) // prints "[1, 2, 3, 4, 5]"
numbers.add(6)
println(readOnlyView) // prints "[1, 2, 3, 4, 5, 6]"

만약 List에 존재하는 유일한 참조가 read-only variety라면, 변경할 수 없는 컬렉션이라고

간주할 수 있습니다.  

이러한 컬렉션을 만드는 간단한 방법은 아래와 같습니다.

val items = listOf(1, 2, 3, 4, 5)

listOf() 메서드는 array list를 구현해서 사용하고 있습니다.

하지만 후에는 메모리 변경이 불가능한 불변 컬렉션 타입이 반환될 수 있습니다.

read-only 타입은 공변성입니다. 이 말은 Rectangle 이 Shape를 상속 받았다고 하면,

List<Rectangle>을 List<Shape> 에 할당할 수 있습니다.

이는 실패를 허용하여서, 변경가능한 컬렉션 타입에서는 허용하지 않습니다.


때때로 변경하지 않을 특정 시점의 콜렉션 스냅 샷을 호출자에게 반환하려는 경우도 있습니다.

class Controller {
private val _items = mutableListOf<String>()
val items: List<String> get() = _items.toList()
}

위의 toList() 확장 메서드는 리스트의 아이템을 복제하기 때문에, 반환된 리스트는

변경되지 않습니다.


lists 와 sets 에는 다양하고 유용한 확장 메서드를 가지고 있습니다.

val items = listOf(1, 2, 3, 4)
items.first() == 1
items.last() == 4
items.filter { it % 2 == 0 } // returns [2, 4]

val rwList = mutableListOf(1, 2, 3)
rwList.requireNoNulls() // returns [1, 2, 3]
if (rwList.none { it > 6 }) println("No items above 6") // prints "No items above 6"
val item = rwList.firstOrNull()

뿐만 아니라 sort, zip, fold, reduce 등과 같은 유틸리티를 제공합니다.


Map의 경우는 아래처럼 인스턴스화할 수 있고 엑세스할 수 있습니다.

val readWriteMap = hashMapOf("foo" to 1, "bar" to 2)
println(readWriteMap["foo"]) // prints "1"
val snapshot: Map<String, Int> = HashMap(readWriteMap)


이상입니다.

다음 포스팅에서는 Ranges 에 대해서 공부합니다.

감사합니다.

반응형