Kotlin

1. 콜렉션의 특징

코틀린에서 제공하는 콜렉션들의 리스트는 다음과 같다.

  • Pair : 값이 두 개인 튜플
  • Tripple : 값이 세 개인 튜플
  • Array : 객체나 프리미티브 타입으로 구성되어 순번이 있고, 크기가 고정된 콜렉션
  • List : 객체들이 정렬된 콜렉션
  • Set : 객체들이 정렬되지 않은 콜렉션
  • Map : 연관 사전 혹은 키와 값의 맵

 

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

  • kotlin.collections 패키지에 Java 콜렉션에 유용한 함수들이 많이 추가되어 사용할 수 있다.
//Java code
for(int i = 0; i < names.size(); i++) {
	System.out.println(names.get(i));
}

 

for-each 를 이용해 직관적으로 사용하기도 했다.

//Java code
for(String name : names) {
	System.out.println(name);
}

 

코틀린은 다음과 같은 코드로 제공한다.

 

// extension.kts

val names = listOf("Tom", "Jerry")

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

// 실행 시,
$ kotlinc-jvm -script extension.kts
class java.util.Arrays$ArrayList
0 Tom
1 Jerry

 

names 는 JDK 의 ArrayList의 인스턴스이지만 코틀린을 사용하여 자바보다 편리하게 사용할 수 있다.

 

1.2. 뷰

이뮤터블 콜렉션은 동시성을 사용하는 함수형 프로그래밍 또는 비동기 처리를 하는 애플리케이션을 사용할 때 훨씬 안정적이라고 한다.

하지만 읽기 전용 뷰가 스레드 안정성을 제공해 준다고 가정할 순 없다.

 

다른 스레드에서 콜렉션을 변경하지 않는다는 보장이 없기 때문에, 두 개의 스레드에서 읽기-쓰기 뷰를 이용해 동시에 한 콜렉션을 변경하지 않도록 주의를 기울여야한다.

 

2. Pair와 Tripple 사용하기

  • 2개와 3개의 객체를 콜렉션으로 만들고 싶을 때 사용한다.
  • Pair와 Tripple 모두 이뮤터블 이다.
  • 3개보다 더 많은 이뮤터블 값들을 그룹핑하고 싶다면 데이터 클래스를 만들어서 사용할 수도 있다.

 

println(Pair("Tom", "Jerry")) // (Tom, Jerry)
println(mapOf("Tom" to "Cat", "Jerry" to "Mouse")) // {Tom=Cat, Jerry=Mouse}

 

// airporttemperatures.kts

fun getTemperatureAtAirport(code: String) : String = "${Math.round(Math.random() * 30) + code.count()} C"

val airportCodes = listOf("LAX", "SFO", "PDX", "SEA")
val temperatures = airportCodes.map { code -> code to getTemperatureAtAirport(code) }

for (temp in temperatures) {
    println("Airport : ${temp.first} : Temperature: ${temp.second}")
}

 

실행 결과

 

$ kotlinc-jvm -script airporttemperatures.kts
Airport : LAX : Temperature: 26 C
Airport : SFO : Temperature: 29 C
Airport : PDX : Temperature: 8 C
Airport : SEA : Temperature: 11 C

 

3. 객체 배열과 프리미티브 배열

  • 배열은 낮은 수준의 최적화가 필요할 때 사용한다.
  • 배열을 만드는 가장 쉬운 방법은 arrayOf() 라는 최상위 함수를 사용하는 것이다.
  • 배열을 만들면 인덱스 연산자 []를 이용해서 요소에 접근할 수 있다.

 

val friends = arrayOf("Tintin", "Snowy", "Haddock", "Calculus")
println(friends::class) // class kotlin.Array
println(friends.javaClass) // class [Ljava.lang.String;
println("${friends[0]} and ${friends[1]}") // Tintin and Snowy

val numbers = intArrayOf(1,2,3)
println(numbers::class) // class kotlin.Array
println(numbers.javaClass) // class [Ljava.lang.Integer;
println("${numbers[0]} and ${numbers[1]}") // 1 and 2

for (i in 0 until numbers.size) {
    println("numbers[$i] : ${numbers[i]}")
}
println(numbers.size) // 3
println(numbers.average()) // 2.0

println(Array(5) { i -> (i + 1) * (i + 1)}.sum()) //55

 

4. List 사용하기

  • 이뮤터블(불변) 리스트를 만들기위해 listOf() 메소드를 사용한다.
  • 뮤터블(변함) 리스트를 만드려면 mutableListOf() 를 사용해 만든다.

 

// lists.kts

val fruits: List<String> = listOf("Apple", "Banana", "Grape")
println(fruits)
println("first's ${fruits[0]}, that's ${fruits.get(0)}")
//first's Apple, that's Apple

println(fruits.contains("Apple")) // true
println("Apple" in fruits) // true

//fruits.add("Orange") // ERROR: unresolved reference: add 

val fruits2 = fruits + "Orange"
println(fruits) // [Apple, Banana, Grape]
println(fruits2) // [Apple, Banana, Grape, Orange]

val noBanana = fruits - "Banana"
println(noBanana) // [Apple, Grape]

println(fruits::class) // class java.util.Arrays$ArrayList
println(fruits.javaClass) // class java.util.Arrays$ArrayList

 

뮤터블 리스트는 다음과 같이 사용 가능함 (되도록이면 listOf() 를 사용하자)

 

// mutablelist.kts

val fruits: MutableList<String> = mutableListOf("Apple", "Banana", "Grape")
println(fruits::class) //class java.util.ArrayList

fruits.add("Orange") // true

 

5. Set 사용하기

  • Set 도 마찬가지로 이뮤터블 setOf(), 뮤터블 mutableSetOf() 메소드를 제공한다.
  • List 와 마찬가지로 뮤터블 메소드로 생성한 경우 add, remove 가 가능하다.

 

// sets.kts

val fruits: Set<String> = setOf("Apple", "Banana", "Apple")
println(fruits) // [Apple, Banana]

println(fruits::class) // class java.util.LinkedHashSet
println(fruits.javaClass) // class java.util.LinkedHashSet

 

6. Map 사용하기

  • 키 - 값 페어를 보관하는 콜렉션
  • mapOf(), mutableMapOf() 가 있다.
  • hashMapOf(), linkedMapOf(), sortedMapOf() 가 있다.

 

// usingmap.kts

val sites = mapOf("6lueparr0t" to "https://6lueparr0t.tistory.com", "rgbplace" to "https://blog.rgbplace.com")
println(sites.size)

println(sites.containsKey("rgbplace")) // true
println(sites.containsValue("rgbplace")) // false
println(sites.contains("rgbplace")) // true
println("6lueparr0t" in sites) // true

val rgbplaceSite: String? = sites.get("rgbplace")
val rgbplaceSite2: String? = sites["rgbplace"]

val blueparr0t = sites.getOrDefault("6lueparr0t", "https://github.com/6lueparr0t")

val sitesWithExample = sites + ("example" to "http://www.example.com")
val withoutRgbplace = sites - "rgbplace"

println(sitesWithExample)
println(withoutRgbplace)
println()

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

println()

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

 

정리 후기

  • 생각보다 '다재다능 코틀린 프로그래밍'의 책 내용을 정리한 사람이 많다.
  • 일단 다 보기 전까지는 블로그에 계속 정리할 생각이지만 다른 코드(로또, 구구단 같은 혹은 알고리즘)를 추후에 조금 곁들여볼까 한다.