본문 바로가기

Language/Kotlin

[Kotlin] 9장. 컬렉션

728x90

컬렉션

컬렉션의 종류로는 List, Set, Map 등이 있으며 자바와는 다르게 불변형(immutable)과 가변형(mutable)으로 나뉜다.

  • List : 불변형 listOf , 가변형 mutableListOf, arrayListOf
  • Set : 불변형 setOf , 가변형 mutableSetOf, hashSetOf, linkedSetOf, sortedSetOf
  • Map : 불변형 mapOf , 가변형 mutableMapOf, hashMapOf, linkedMapOf, sortedMapOf

변수 선언시에 불변형인 val의 사용을 권장하듯이 컬렉션도 되도록이면 읽기 전용인 불변형으로 사용하는 것을 권장.

List

불변형 List

값을 변경할 수 없는 불변형 List를 만드려면 헬퍼 함수인 listOf()를 사용할 수 있다.

헬퍼 함수란, List 같은 컬렉션은 직접 사용해 생성하지 않고 특정 함수의 도움을 통해 생성하는데 이때 사용하는 함수를 헬퍼 함수라고 한다.

 

public fun <T> listOf(vararg elements: T) : List<T>

 

vararg는 가변 인자를 받을 수 있기 때문에 원하는 만큼 요소를 지정할 수 있으며, List<T>를 반환한다. 이 때, 형식 매개 변수 <T>는 지정하지 않으면 기본 값인 <Any>로 사용되며 어떤 자료형이든 혼합이 가능하다.

for문을 사용하여 컬렉션의 요소에 접근이 가능하며, indices멤버를 추가하여 인덱스를 사용할 수 있다.

 

val sam = listOf(...)

for (item in sam) {
	println(item)
}

for (index in sam.indices) {
	println("sam[$index] = ${sam[index]}")
}

 

 

listOfNotNull() 함수를 사용하여 초기화 하게 되면 null을 제외한 요소만 반환해 List를 구성할 수 있다.

List의 주요 메서드

  • get : 특정 인덱스를 인자로 받아 해당 요소 반환
  • indexOf : 인자로 받은 요소가 첫 번째로 나타나는 인덱스 반환. 없으면 -1
  • lastIndexOf : 인자로 받은 요소가 마지막으로 나타나는 인덱스 반환. 없으면 -1
  • listIterator : 목록에 있는 iterator 반환
  • subList : 특정 인덱스의 from과 to 범위에 있는 요소 목록을 반환

가변형 List 

arrayListOf, mutableListOf 가 있으며, 가변형이기 때문에 add() 와 remove()를 사용하여 요소를 추가, 삭제 할 수 있으며 대괄호를 사용하여 값을 변경해 줄 수 있다.

단, 반환되는 자료형은 각각 ArrayList, MutableList 임을 기억해두어야 한다.

List와 배열의 차이

List는 Array<T>와 사용 방법이 비슷하다. 하지만 Array 클래스에 의해 생성되는 배열 객체는 고정된 크기의 메모리를 가지고 있는 반면, List는 메모리 크기가 고정되어 있지 않기 때문에 자료구조에 따라 늘리거나 줄이는 것이 가능하다.

또한, Array<T>는 제네릭 관점에서 무변성이지만, List<T>는 공변성이다.

 

Set과 Map

set과 map의 mutable 함수는 list와 비슷하게 사용된다. 하지만 hash, sorted, linked 함수의 경우 다른점이 있으므로 확인해봐야 한다.

Set

set은 집합의 개념이기 때문에 동일한 요소를 중복해서 가질 수 없다. 즉, 모든 요소가 유일해야 한다.

  • hashSetOf 함수 : 해시 테이블에 요소를 저장할 수 있는 HashSet 컬렉션을 만든다. 해시 테이블은 키와 인덱스를 이용해 검색과 변경 등을 매우 빠르게 처리할 수 있다. HashSet은 불변성 선언이 없기 때문에 추가 및 삭제 기능을 수행할 수 있다.
  • sortedSetOf 함수 : TreeSet 컬렉션을 정렬된 상태로 반환. TreeSet은 저장된 데이터의 값에 따라 정렬되는데 개선된 이진 탐색 트리인 레드 블랙 트리 알고리즘을 사용해 자료구조를 구성한다. HashSet보다 성능이 좀 떨어지고 데이터 추가, 삭제에 시간이 걸리지만 검색과 정렬이 뛰어나다.
  • linkedSetOf 함수 : 링크드 리스트를 사용해 해시테이블에 요소를 저장한다. 저장된 순서에 따라 값이 정렬되며, hash, tree set 보다 느리지만, 포인터 연결을 통해 메모리를 효율적으로 사용한다.

Map

자바의 Map을 이용하고 있으며 키와 값으로 구성된 요소를 저장한다. 여기서 키와 값은 모두 객체이다. 키는 중복될 수 없지만 값은 중복 저장될 수 있다.

map은 키와 값의 쌍으로 사용하기 때문에 다음과 같이 사용한다.

 

 

map의 값을 출력하기 위해 대괄호를 사용할 때는 index가 아니라 키 값을 사용하고 있다는 것에 주의해야 한다.

가변형 mutableMapOf 함수에서눈 put(key, value)로 요소를 추가하고, remove(key)를 통해 요소를 제거하며, putAll을 통해 Map 객체를 통합할 수 있다.

 

hashMapOf, sotredMapOf, linkedMapOf 또한 set과 같이 사용할 수 있으며, 내부 구조 또한 set과 비슷하게 되어있어 마찬가지로 사용하면 된다.

시퀀스 활용하기

Kotlin의 시퀀스는 순차적인 컬렉션으로 요소의 크기를 특정하지 않고, 나중에 결정할 수 있는 특수한 컬렉션이다. 따라서 toList() 나 count() 같은 최종 연산에 의해 결정된다.

generateSequence()

특정 값을 생성하기 위해 generateSequence(seed)를 사용한다. 이 때, 시드 인수에 의해 시작 요소의 값이 결정된다.

 

 

이와 같이 사용하며, seed 값이 10 이기 때문에 시작 요소는 10으로 시작한다. 4씩 증가하도록 되어있고, take(5)를 통해 5개의 요소가 저장되게 된다.

따라서 출력되는 값은 10, 14, 18, 22, 26 이 되는 것이다.

 

map이나 filter 연산을 사용하여 새로운 컬렉션을 반환할 수 있다.

 

asSequence()

중산 연산 결과 업이 한 번에 끝까지 연산한 후 결과를 반환하려면 asSequence()를 사용할 수 있다. filter나 map을 메서드 체이닝하여 사용할 경우 순차적 연산이기 때문에 시간이 많이 걸릴 수 있지만, asSequence()를 사용하면 병렬 처리 되기 때문에 처리 성능이 좋아진다.

 

 

asSequence를 사용하게 되면, 각 map, filter 과정만으로는 결과 도출이 불가능 하고, toList를 호출하는 과정에서 모든 연산이 수해오디고 새로운 결과물이 listSeq에 저장되게 된다.

 

 

728x90