콜랙션 사용하기 🫂

Record For a Better Life ·2022년 9월 24일
0

다재다능코틀린

목록 보기
4/6

5-1 콜렉션의 특징

콜렉션의 종류

  1. Pair : 값이 두 개인 튜플
  2. Triple : 값이 세 개인 튜플
  3. Array : 객체나 프리미티브 타입으로 구성되어 순번이 있고, 크기가 고정된 콜렉션
  4. List : 객체 정렬 콜렉션
  5. Set : 객체 정렬 X 콜렉션
  6. Map : 연관 사전 혹은 키와 값의 앱

자바에서도 이미 충분한 collection을 제공하고 있기에, 코틀린이 어떤 역할을 하는지 궁금하다.
코틀린이 제공해주는 collection의 진화는 총 두가지다.

  1. 함수 확장

코틀린이 제공하는 편리한 메소드

kotlin.collections 패키지에 Java 콜렉션에 유용한 함수들이 많음

자바와 비교하기

Java의 명렬형 스타일 for-Each가 아닌 함수형 스타일의 forEach문을 사용한다면 인덱스 사용 불가

⬇️

Kotlin의 withIndex() 메소드 -> 인덱스와 값 모두를 편하게 얻게 해줌

for ((index, value) in names.withIndex()){ """ }

immutable collection : 동시성을 사용하는 함수형 프로그래밍 또는 비동기 처리를 하는 애플리케이션을 사용할 때 훨씬 안정적이다.

Java : 대부분의 collection은 mutable이고, 최근 이뮤터블 콜렉션이 생겼지만, 변경 시도를 하면 실행시간에 UnsupportedOperationException이 나옴

⬇️

Kotlin : 연산이 불가능함을 실행 시간이 되어서야 알리지 않는다. 무슨말이지..?

list, set, map의 두 가지 뷰 : immutable (읽기전용 뷰), mutable (읽기-쓰기 뷰)
-> 사용 시 오버헤드가 없고, 컴파일 시간이나 실행 시간에 변환이 발생하지 X

읽기 전용 뷰가 thread safety를 제공해준다고 보장할 수는 없음.
읽기전용 참조는 mutable collectiond이며 콜렉션을 변경할 수는 없지만, 다른 스레드가 참조하고 있는 콜렉션을 변경하지 않았다는 걸 보장해 주지 않는다...?
여러 개의 뷰가 같은 인스턴스를 참조하고 있는 중이고, 그 중 일부는 읽기 전용, 일브는 읽기-쓰기 용으로 사용된다면 사용 시 두 개의 쓰레드에서 읽기-쓰기 뷰를 이용해서 동시에 한 콜렉션을 변경하지 않도록 주의!!

5-2 페어와 트리플 사용하기

튜플- 2, 3개의 튜플만 허용

  1. Pair의 생성자를 이용해서 인스턴트 생성
  2. to() 확장함수를 이용해서 Map의 엔트리가 될 페어 생성
println(Pair("Tom", "Jerry"))
println(mapOf("Tom" to "Cat", "Jerry" to "Mouse"))

페어의 장점 예제 : 공항의 온도를 공항 코드별로 수집해주는 코드이다.

val airportcodes = listOf("LAX", "SFO", "PDX", "SEA")
val temperarues = airportcodes.map { code -> code to getTemperatureAtAirport(code) }
for (temp in temperatures) {
	println("Airport: ${temp.first} : Temperature: ${temp.second}")
    }

코틀린의 페어는 간결한 코드를 만들 수 있을 뿐만 아니라, 컴파일 시간에서 타입 안정성 또한 제공한다.

  • 특히 2개의 값을 다룰 때 유용하다.
  • 3개의 객체가 필요하다면 페어 대신 트리플!

페어와 트리플은 모두 immutable, mutable collection의 값들을 취급하는 콜렉션을 위해선 배열이 좋은 선택이다.

5-3 객체 배열과 프리미티브 배열

배열은 낮은 수준의 최적화가 필요할 때만 사용,
그 외엔 List같은 자료구조를 사용하라!

  • 배열을 만드는 가장 쉬운 방법 : arrayof() -> 최상위 함수
    (intArray를 사용하면 arrayOf()처럼 Integer 클래스의 오버헤드가 큰 배열이 만들어지지 않고, int 배열이 만들어짐!)

5-4 리스트 사용하기

이뮤터블과 뮤터블을 선택할 수 있는 경우에는 이뮤터블을 선호해야한다! 하지만 꼭 필요해서 뮤터블 리스트를 만들어야 한다면 mutableList()를 사용해라

listof() function -> immutable, 리스트의 요소들에 접근하기 위해 전통적인 get() 메소드 사용가능! 하지만 get() 대신 []를 사용하는 편이 좋다.

  • 리턴하는 참조를 사용할 때 리스트를 변경할 수 없다. 인터페이스는 변화를 허용하거나 리스트를 바꿀 수 있는 권한을 가진 메소드가 없기 때문이다.

    이런 뷰를 제공해주기 때문에, 코틀린은 뷰의 변경 불가능한 부분을 이용해서 코드를 더 안전하게 만ㄷ르고 실행 시간에 오버헤드나 변경이 없도록 만든다. 😬

다른 요소를 추가하고 싶다면 add() 대신 + 연산자를 사용할 수 있다. 기존 list를 변경시키는 것이 아닌, 카피하면서 새로운 list를 만들고 새로운 요소를 추가하는 것이다!

  • 연산자 또한 존재한다. 기존 리스트에서 특정 요소를 제외한 새로운 리스트를 만들 수 있다.

5-5 셋 사용하기

셋은 정렬되지 않은 요소의 모음이다. 이뮤터블/읽기 전용 버전과, 뮤터블/읽기-쓰기 버전 모두 있다. (setof(), Mutablesetof())
+ hashSetOf(), linkedSetOf(), sortedSetOf()

  • 셋은 중복 요소 허용 X, 중복 값은 누락됨
  • 리스트와 마찬가지로 MutableSet과 Set은 +, -, contations, in 등 많은 함수가 존재함

5-6 맵 사용하기

key-value 페어를 보관하는 collection 🫥
JDK의 맵에서 사용 가능한 모든 method는 mutable interface에서 사용이 가능하다. immutable에서는 읽기 전용만 가능하다.

  • mapOf()
  • mutableMapOf()
  • hashMapOf()
  • linkedMapOf()
  • sortedMapOf()

immutable, 읽기 전용의 Map 인터페이스를 만들고 요소에 접근하자!
ex>

val sites = mapOf("pragprog" to "https://www.pragprog.com", "agiledeveloper" to "https://agiledeveloper.com")

# containsKey(), containsValue() 메소드를 통해 각 존재여부 파악 가능!

get() 메소드는 key가 맵에 존재하지 않을 때 nullable 타입 리턴, 오류 🤒
-> nullable 참조를 피하기 위해 키가 없으면 기본값을 리턴하도록 함 !!
(getOrDefault(key값, default값) 메소드)

mapOf() 함수는 읽기 전용 참조만 전달해주므로 Map 변경 불가능, 하지만 key-value pair를 추가해서 새로운 맵 생성 가능~!!

val sitesWithExample = sites + ("example" to "https://www.example.com")

for문을 사용한 구조분해 :

for ((key, value) in sites) {
	println( "$key --- $value")
}

정리, 코틀린은 Java의 콜렉션을 확장시키는 동시에, 읽기 전용 뷰를 통해 컴파일 시간의 안정성도 향상시킴. 함수형 코드를 쓰거나, 동시성 코드를 작성하거나, 비동기 프로그램을 만들 때는 읽기 전용 뷰를 사용해야 한다.
작은 크기의 콜렉션 - pair & tripple 사용
크고 고정된 크기의 콜렉션 - Array

이렇게 5챕터 정리도 끝이 났다 ~~!! 🫶🫶
이번 챕터에서는 반복자를 이용하는 방법을 배웠다.
다음 챕터에서는 코틀린이 컴파일 시 타입 안정성을 제공하는 완전히 새로운 방법에 대해 알아본다고 한다. 타입 안정성은 프로그래밍에 있어서 개인적으로 상당히 많이 중요하다고 생각하고 있기 때문에 매우 기대중..!

profile
모든 것을 기록하는 벨로그 💻

0개의 댓글