List, Set, Map은 데이터를 저장하는 기본 자료구조들을 한 곳에 모아 관리와 이용을 편하게 하기 위해 제공되는 프레임워크를 구성하고 있다.
이를 컬렉션이라고 하는데, Kotlin에서 컬렉션은 다른 프로그래밍 언어와 달리, 변경 가능한 컬렉션(Mutable)과 변경 불가능한 컬렉션(Immutable)이 있다.
1. List
Kotlin의 List는 기본적으로 변경 불가능한, Immutable 한 방식이다. 생성자에 List의 길이와 초기화를 위한 람다식을 넣어주는 것으로 객체를 생성해 줄 수 있다.
변경 불가능한 Immutable List
fun main(){
val list: List<Int> = List(5, {i -> i})
println(list)
}
// 실행 결과: [0, 1, 2, 3, 4]
또는 listOf함수를 이용해서 객체를 생성해 줄 수도 있다.
fun main() {
val list = listOf(1, 2, 3, 4, 5)
println(list)
}
// 실행 결과: [1, 2, 3, 4, 5]
List 객체의 각 요소에는 get() 메소드 없이 대괄호 [] 를 통해 접근할 수 있다.
fun main() {
val list = listOf(1, 2, 3, 4, 5)
for(i in 0 until list.size){
println(list[i])
}
}
// 실행 결과
// 1
// 2
// 3
// 4
// 5
List가 Immutable한 객체이기 때문에 기존에 들어있는 값을 변경할 수는 없다.
val list = listOf(1, 2, 3, 4, 5)
list[0] = 10 // Error
변경 가능한(Mutable) List 만들기
기본적으로 변경 불가능한, Immutable한 List를 Mutable List로 만들기 위해서는 MutableList 또는 ArrayList 클래스를 이용하면 된다.
MutableList나 ArrayList 역시 생성자에서 초기화 하는 방법과 mutableListOf() 나 arrayListOf() 함수를 통해 초기화 하는 방법이 있다.
1) MutableList & mutableListOf
fun main() {
val array1 = MutableList<Int>(5, {i -> i})
array1[0] = 10
println(array1)
val array2 = mutableListOf(1, 2, 3)
array2.add(4)
println(array2)
}
// 실행 결과: [10, 1, 2, 3, 4]
// 실행 결과: [1, 2, 3, 4]
2) ArrayList & arrayListOf
fun main() {
val array1 = ArrayList<Int>()
array1.add(1)
array1.add(2)
println(array1)
val array2 = arrayListOf(1, 2, 3)
array2.add(4)
println(array2)
}
// 실행 결과: [1, 2]
// 실행 결과: [1, 2, 3, 4]
2. Set
Set은 List와 다르게 중복을 허용하지 않고 순차적이지 않은 데이터의 집합이다. Set도 List와 마찬가지로 Mutable 타입과 Immutable 타입이 있다.
Immutable 타입
Set 클래스는 Immutable 타입이고, 이는 setOf() 함수에 의해 생성된다.
fun main() {
val set1 = setOf<Int>(3, 3, 1, 2)
println(set1)
}
// 실행 결과: [3, 1, 2]
위 코드의 실행결과에서 볼 수 있듯이 Set에서는 중복을 허용하지 않으므로, 중복된 '3' 데이터가 하나 제거되어 출력되는 것을 확인할 수 있다.
Mutable 타입
Mutable 타입의 Set은 mutableSetOf, hashSetOf, linkedSetOf, sortedSetOf 등의 함수를 이용해서 생성할 수 있다.
각 함수는 MutableSet<T>, HashSet<T>, LinkedHashSet<T>, TreeSet<T> 객체를 만들어 반환한다.
fun main() {
val set1: MutableSet<Int> = mutableSetOf(3, 3, 1, 2)
set1.remove(2)
set1.add(5)
println(set1)
val set2: HashSet<Int> = hashSetOf(3, 3, 1, 2)
set2.remove(2)
set2.add(5)
println(set2)
}
// 실행 결과: [3, 1, 5]
// 실행 결과: [1, 3, 5]
위 코드에서 HashSet<T> 객체에서 출력된 순서를 자세히 보면 HashSet 클래스는 'Key' 값의 해시코드(Hash Code) 순으로 검색된다.
3. Map
Map은 '키(Key)'와 '값(Value)'으로 이루어진 한 쌍의 데이터를 관리하기 위한 집합으로, 효율적인 검색을 지원하는 컬렉션이다. Map은 순차적이지 않고, '키'는 중복될 수 없지만 '값'은 중복될 수 있다.
Immutable 타입
Immutable 타입의 Map은 mapOf 함수를 이용해서 생성된다.
fun main() {
val map1: Map<String, Int> = mapOf("one" to 1, "two" to 2, "three" to 3)
val map2: Map<String, Int> = mapOf(Pair("four",4), Pair("five", 5))
println(map1)
println(map2)
println(map1.get("one"))
println(map2.get("five"))
}
// 실행 결과: {one=1, two=2, three=3}
// 실행 결과: {four=4, five=5}
// 실행 결과: 1
// 실행 결과: 5
Mutable 타입
Mutable 타입의 Map은 mutableMapOf, hashMapOf, linkedMapOf, sortedMapOf 등의 함수에 의해 생성되며, 각각 MutableMap<k, v>, HashMap<k, v>, LinkedHashMap<k, v>, SortedMap<k, v> 객체를 만들어 반환한다.
fun main() {
val map1: MutableMap<String, Int> = mutableMapOf("one" to 1)
val map2: HashMap<String, Int> = hashMapOf("one" to 1, "two" to 2, "three" to 3)
println(map1)
println(map2)
map1.put("ten", 10)
map2.set("two", 20)
map2.remove("three")
println(map1)
println(map2)
}
// 실행 결과: {one=1}
// 실행 결과: {two=2, three=3, one=1}
// 실행 결과: {one=1, ten=10}
// 실행 결과: {two=20, one=1}
위 코드를 보면 HashMap 역시 '키' 값의 해시 코드 순으로 출력된다.