본문 바로가기
Kotlin/Kotlin 프로그래밍

[Kotlin] 컬렉션(Collection)의 확장함수

by 주 녕 2021. 5. 27.
728x90

모든 내용은 Do it! 안드로이드 앱 프로그래밍을 바탕으로 정리한 것입니다. 

 

[이전 포스팅]

코틀린의 컬렉션 - List, Set, Map에 대한 내용은 아래 포스팅 참고

 

[Kotlin] 컬렉션(Collection) - List

모든 내용은 Do it! 코틀린 프로그래밍을 바탕으로 정리한 것입니다. 컬렉션(Collection) 컬렉션은 자주 사용하는 기초적인 자료구조를 모아 놓은 일종의 프레임워크로 표준 라이브러리로 제공하고

junyoung-developer.tistory.com

 

[Kotlin] 컬렉션(Collection) - Set, Map

모든 내용은 Do it! 코틀린 프로그래밍을 바탕으로 정리한 것입니다. 컬렉션(Collection) 컬렉션은 자주 사용하는 기초적인 자료구조를 모아 놓은 일종의 프레임워크로 표준 라이브러리로 제공하고

junyoung-developer.tistory.com

 

컬렉션의 확장 함수

  • 연산자(Operator) 기능의 메서드 : 더하고 빼는 등의 기능
  • 집계(Aggregator) 기능의 메서드 : 최대, 최소, 집합, 총합 등의 계산 기능
  • 검사(Check) 기능의 메서드 : 요소를 검사하고 순환하는 기능
  • 필터(Filtering) 기능의 메서드 : 원하는 요소를 골라내는 기능
  • 변환(Transforming) 기능의 메서드 : 뒤집기, 정렬, 자르기 등의 변환 기능

 

컬렉션의 연산

fun main() {
    val list1: List<String> = listOf("one", "two", "three")
    val list2: List<Int> = listOf(1, 3, 4)
    val map1 = mapOf("hi" to 1, "hello" to 2, "Goodbye" to 3)
    
    println(list1 + "four")  // [one, two, three, four]
    println(list2 + 1)  // [1, 3, 4, 1]
    println(list2 + listOf(5, 6, 7))  // [1, 3, 4, 5, 6, 7]
    println(list2 - 1)  // [3, 4]
    println(list2 - listOf(3, 4, 5))  // [1] - 일치하는 요소 제거
    println(map1 + Pair("Bye", 4))  // {hi=1, hello=2, Goodbye=3, Bye=4}
    println(map1 - "hello")  // {hi=1, Goodbye=3}
    println(map1 + mapOf("Apple" to 4, "Orange" to 5))  // {hi=1, hello=2, Goodbye=3, Apple=4, Orange=5}
    println(map1 - listOf("hi", "hello"))  // {Goodbye=3} - 일치하는 값 제거
}
  • 일반적인 연산자 +와 -를 사용해 컬렉션 요소를 더하거나 뺄 수 있음
  • 연산자 +와 -를 사용해 컬렉션 자체를 더하거나 뺄 수 있음
    • listOf(), Pair(), mapOf() 등을 더하거나 빼는 방법으로 요소를 병합하거나 제거할 수 있음

 

컬렉션의 집계

fun main() {
    val list = listOf(1, 2, 3, 4, 5, 6)
    val listPair = listOf(Pair("A", 300), Pair("B", 200), Pair("C", 100))
    val map = mapOf(11 to "Java", 22 to "Kotlin", 33 to "C++")
    ...
}

위의 3개의 컬렉션을 예시로 하여 집계 확장 함수를 설명합니다!

 

요소의 순환

    list.forEach { print("$it") }
    println()
    list.forEachIndexed { index, value -> println("index[$index]: $value") }

    val returnedList = list.onEach { print(it)}
    println()
    val returnedMap = map.onEach { println("key: ${it.key}, value: ${it.value}") }
    println("returnedList = $returnedList")  // returnedList = [1, 2, 3, 4, 5, 6]
    println("returnedMap = $returnedMap")  // returnedMap = {11=Java, 22=Kotlin, 33=C++}
  • forEach : 각 요소를 람다식으로 처리 (컬렉션 반환X)
  • forEachIndexed : 각 요소와 인덱스를 람다식으로 처리
  • onEach : 각 요소를 람다식으로 처리하고 각 컬렉션을 반환받음

 

요소의 개수

    println(list.count { it % 2 == 0})  // 3
    println(list.count())  // 6
  • count : 특정 조건에 일치하는 요소의 개수를 반환함
    • 요소를 it으로 받아 1, 2, 3, 4, 5, 6 중에서 count에 의해 람다식 조건이 짝수인 요소의 개수를 반환함

 

최댓값과 최솟값

    println(list.max())  // 6
    println(list.min())  // 1 

    println("maxBy: "+map.maxBy { it.key })  // maxBy: 33=C++
    println("minBy: "+map.minBy { it.key })  // minBy: 11=Java
  • max / min : 최댓값 요소와 최솟값 요소 반환
  • maxBy / minBy : 최댓값과 최솟값으로 나온 요소 it에 대한 식의 결과
    • 람다식에 의해 컬렉션을 처리하며, 위의 예제에서는 키를 기준으로 최대, 최소를 반환함

 

요소에 정해진 식

    println(list.fold(4) { total, next -> total + next })  // 4 + 1 + ... + 6 = 25
    println(list.fold(1) { total, next -> total * next })  // 1 * 1 * ... * 6 = 720

    println(list.foldRight(4) { total, next -> total + next })  // 25
    println(list.foldRight(1) { total, next -> total * next })  // 720

    println(list.reduce { total, next -> total + next })  // 21
    println(list.reduceRight { total, next -> total + next })  // 21 
  • fold(초기값) : list의 모든 요소에 대해 초기값이 정해지고 모든 요소가 처리됨
  • foldRight(초기값) : fold와 동일하지만 4+6+5+...+1과 같이 요소의 오른쪽부터 처리됨
  • reduce : fold와 동일하지만 초기값을 사용하지 않음
  • reduceRight : foldRight와 동일하지만 초기값을 사용하지 않음

 

요소 합산

    println(listPair.sumBy { it.second })  // 600
  • sumBy : 식에서 도출된 모든 요소를 합한 결과 반환
    • 위의 예제에서는 Pair로 묶인 요소의 두번째(second)를 합한 결과가 반환됨

 

컬렉션의 검사

fun main() {
    val list = listOf(1, 2, 3, 4, 5, 6)
    val listPair = listOf(Pair("A", 300), Pair("B", 200), Pair("C", 100))
    val map = mapOf(11 to "Java", 22 to "Kotlin", 33 to "C++")
    ...
}

위의 3개의 컬렉션을 예시로 하여 검사 확장 함수를 설명합니다!

 

요소의 일치 여부 검사

    println(list.all { it < 10 })  // true
    println(list.all { it % 2 == 0 })  // false

    println(list.any { it % 2 == 0 })  // true
    println(list.any { it > 10 })  // false
  • all : 람다식에서 모든 요소가 일치할 때 true 반환
  • any : 최소한 하나 혹은 그 이상의 특정 요소가 일치하면 true 반환

 

특정 요소의 포함 / 존재 여부 검사

    println("contains: " + list.contains(2))  // contains: true
    println(2 in list)  // true
    println(map.contains(11))  // true
    println(11 in map)  // true

    println("containsAll: "+list.containsAll(listOf(1, 2, 3)))  // containsAll: true
  • contains : 요소가 포함되어 있는지를 검사하며, 포함되어 있으면 true 반환
    • 범위 연산자 in을 사용해서 요소의 포함 여부를 확인할 수 있음
  • containsAll : 모든 요소가 포함되어 있는지 검사하며, 포함되어 있으면 true 반환
    println("none: "+list.none())  // none: false
    println("none: "+list.none { it > 6 })  // none: true

    println(list.isEmpty())  // false
    println(list.isNotEmpty())  // true
  • none() : 검사했을 때 요소가 없으면 true, 있으면 false 반환
  • isEmpty() : 컬렉션이 비어있으면 true를 반환
  • isNotEmpty() : 컬렉션이 비어있지 않다면 true를 반환

 

컬렉션의 필터

fun main() {
    val list = listOf(1, 2, 3, 4, 5, 6)
    val listMixed = listOf(1, "Hello", 3, "World", 5, 'A')
    val listWithNull = listOf(1, null, 3, null, 5, 6)
    val listRepeated = listOf(2, 2, 3, 4, 5, 5, 6)
    val map = mapOf(11 to "Java", 22 to "Kotlin", 33 to "C++")
    ...
}

위의 5개의 컬렉션을 예시로 하여 필터 확장 함수를 설명합니다!

 

특정 요소 골라내기

    println(list.filter { it % 2 == 0 })  // [2, 4, 6]
    println(list.filterNot { it % 2 == 0 })  // [1, 3, 5]
    println(listWithNull.filterNotNull())  // [1, 3, 5, 6]
  • filter() : 식에 따라 요소 골라내는 메서드
  • filterNot() : 식 이외에 요소를 골라내는 메서드
  • filterNotNull() : 컬렉션에서 null을 제외하기 위한 메서드
    println("filterIndexed: "+list.filterIndexed { index, value -> index != 1 && value % 2 == 0 })
    // filterIndexed: [4, 6]
    
    val mutList = list.filterIndexedTo(mutableListOf()) { index, value -> index != 1 && value % 2 == 0 }
    println("filterIndexedTo: $mutList")
    // filterIndexedTo: [4, 6]
  • filterIndexed() : 식의 결과를 인덱스와 함께 추출
  • filterIndexedTo() : 인덱스를 포함한 결과를 추출 후 컬렉션으로 반환
    println("filterKeys: " + map.filterKeys { it != 11 })  // filterKeys: {22=Kotlin, 33=C++}
    println("filterValues: " + map.filterValues { it == "Java" })  // filterValues: {11=Java}
  • filterKeys : 요소를 it으로 받아서 키에 대한 조건에 맞는 부분을 반환
  • filterValues : 요소를 it으로 받아서 값에 대한 조건에 맞는 부분을 반환
    println("filterIsInstance: " + listMixed.filterIsInstance<String>())  // filterIsInstance: [Hello, World]
  • filterIsInstance<T>() : 여러 자료형 중 원하는 자료형(T)을 골라낼 수 있는 필터 

 

특정 범위 자르거나 반환하기

    println("slice: " + list.slice(listOf(0, 1, 2)))  // slice: [1, 2, 3]
  • slice() : 특정 범위의 인덱스를 가진 List의 인자를 사용해 기존 List에서 요소들을 잘라냄
    println(list.take(2))  // [1, 2]
    println(list.takeLast(2))  // [5, 6]
    println(list.takeWhile { it < 3 })  // [1, 2]
  • take(n) : n개의 요소를 가진 List를 반환
  • takeLast(n) : 마지막에서 부터 n개의 요소를 가진 List를 반환
  • takeWhile : 조건식에 따라 해당 요소를 반환

 

특정 요소 제외

    println(list.drop(3))  // [4, 5, 6]
    println(list.dropWhile { it < 3 })  // [3, 4, 5, 6]
    println(list.dropLastWhile { it > 3 })  // [1, 2, 3]
  • drop(n) : 앞의 n개의 요소를 제외한 List를 반환
  • dropWhile, dropLastWhile : 조건식에 따라 요소를 제외하고 List를 반환

 

각 요소 반환

    println("component1(): " + list.component1())  // component1(): 1
  • componentN() : N번째 요소 반환
    • 여기서 N은 인덱스 번호가 아닌 요소의 순서 번호

 

합집합과 교집합

    println("distinct: " + listRepeated.distinct())  
    // val listRepeated = listOf(2, 2, 3, 4, 5, 5, 6)
    // distinct: [2, 3, 4, 5, 6]
    
    println("intersect: " + list.intersect(listOf(5, 6, 7, 8)))  // intersect: [5, 6]
  • distinct() : 여러 중복 요소가 있는 경우 1개로 취급해 다시 컬렉션을 List로 반환함 == 합집합
  • intersect() : 겹치는 요소만 골라내 List로 반환 == 교집합

 

요소의 매핑

fun main() {
    val list = listOf(1, 2, 3, 4, 5, 6)
    val listWithNull = listOf(1, null, 3, null, 5, 6)
    ...
}

위의 2개의 컬렉션으로 요소의 매핑 확장 함수를 설명합니다!

 

    println(list.map { it * 2 })  // [2, 4, 6, 8, 10, 12]

    val mapIndexed = list.mapIndexed { index, it -> index * it }
    println(mapIndexed)  // [0, 2, 6, 12, 20, 30]

    println(listWithNull.mapNotNull { it?.times(2) })
    // [2, 6, 10, 12]
  • .map() : 식을 적용해 새로운 컬렉션을 만들 수 있게 하는 메서드
    • forEach()와 비슷해보이지만 주어진 컬렉션을 전혀 건드리지 않는다는 점에서 더 안전함
  • mapIndexed : 인덱스를 포함하고 주어진 식을 적용하여 새로운 컬렉션 반환
  • mapNotNull : null을 제외하고 식을 적용해 새로운 컬렉션 반환
    println(list.flatMap { listOf(it, 'A') })  // [1, A, 2, A, 3, A, 4, A, 5, A, 6, A]
    val result = listOf("abc", "12").flatMap { it.toList() }
    println(result)  // [a, b, c, 1, 2]
  • flatMap : 각 요소에 식을 적용한 후 다시 합쳐 새로운 컬렉션을 반환
    val grapMap = list.groupBy { if (it % 2 == 0) "even" else "odd" }
    println(grapMap)  // {odd=[1, 3, 5], even=[2, 4, 6]}
  • groupBy : 주어진 식에 따라 요소를 그룹화하고 이것을 다시 Map으로 반환함

 

요소의 처리와 검색

fun main() {
    val list = listOf(1, 2, 3, 4, 5, 6)
    val listPair = listOf(Pair("A", 300), Pair("B", 200), Pair("C", 100), Pair("D", 200))
    val listRepeated = listOf(2, 2, 3, 4, 5, 5, 6)
...
}

위의 3개의 컬렉션으로 요소의 처리, 검색 확장 함수를 설명합니다!

 

    println("elementA: " + list.elementAt(1))  // elementA: 2

    println("elementAtOrElse: " + list.elementAtOrElse(10, { 2 * it }))  // elementAtOrElse: 20
    println("elementAtOrNull: " + list.elementAtOrNull(10))  // elementAtOrNull: null
  • elementAt(N) : 인덱스에 해당하는 요소 반환
    • 범위를 벗어나면 안됨 
    • 범위를 벗어나면 IndexOutOfBoundsException 오류 발생
  • elementAtOrElse : 인덱스를 벗어나는 경우 식에 따라 결과를 반환함
  • elementAtOrNull : 인덱스를 벗어나는 경우 null을 반환함
    println("first: " + listPair.first { it.second == 200 })  // first: (B, 200)
    println("last: " + listPair.last { it.second == 200 })  // last: (D, 200)
    
    println("firstOrNull: " + listPair.firstOrNull { it.first == "E" })  // firstOrNull: null
    println("lastOrNull: " + listPair.lastOrNull { it.first == "E" })  // lastOrNull: null
  • first / last : 식에 일치하는 첫/마지막 요소 반환
  • firstOrNull / lastOrNull : 식에 일치하지 않은 경우 null을 반환
    println("indexOf: " + list.indexOf(4))  // indexOf: 3
    println("indexOfFirst: " + list.indexOfFirst { it % 2 == 0 })  // indexOfFirst: 1
    println("lastIndexOf: " + listRepeated.lastIndexOf(5))  // lastIndexOf: 5
    println("indexOfLast: " + list.indexOfLast { it % 2 == 0 })  // indexOfLast: 5
  • indexOf / lastIndexOf : 주어진 요소에 일치하는 첫/마지막 인덱스를 반환함
  • indexOfFirst / indexOfLast : 람다식에 일치하는 첫/마지막 요소의 인덱스를 반환, 없으면 -1 반환
    println("single: " + listPair.single { it.second == 100 })  // single: (C, 100)
    println("singleOrNull: " + listPair.singleOrNull { it.second == 500 })  // singleOrNull: null
  • single : 해당 조건식에 일치하는 요소를 하나 반환함
    • 일치하는 요소가 하나 이상인 경우 예외가 발생할 수 있음
  • singleOrNull : 조건식에 일치하는 요소가 없거나 일치하는 요소가 하나 이상이면 null을 반환함
    println("binarySearch: " + list.binarySearch(3))  // binarySearch: 2
    println("find: " + list.find { it > 3 })  // find: 4
  • binarySearch(n) : 인자로 주어진 요소에 대해 이진 탐색 후 인덱스를 반환함
    • 중복된 요소가 있는 경우에 해당 요소가 원하는 순서에 있는 요소인지는 보장하지 않음
  • find : 조건식에 만족하는 첫 번째 검색된 요소를 반환하고, 없으면 null을 반환함

 

컬렉션의 변환

fun main() {
    val list1 = listOf(1, 2, 3, 4, 5, 6)
    val list2 = listOf(2, 2, 3, 4, 5, 5, 6, 7)

    println(list1.union(list2))  // [1, 2, 3, 4, 5, 6, 7]

    println(list1.plus(list2))  // [1, 2, 3, 4, 5, 6, 2, 2, 3, 4, 5, 5, 6, 7]

    val part = list1.partition { it % 2 == 0 }
    println(part)  // ([2, 4, 6], [1, 3, 5])

    val zip = list1.zip(listOf(7, 8))
    println(zip)  // [(1, 7), (2, 8)]
}
  • union() : 두 List 컬렉션을 병합하고, 중복된 요소 값은 하나만 유지함 → Set 컬렉션을 반환함
  • plus() / + : 중복 요소를 포함하여 합침 → List 컬렉션을 반환함
  • partition : 조건식의 결과(boolean)에 따라 List 컬렉션을 2개로 분리함
    • true에 해당하는 값이 첫 번째 위치에 반환, false에 해당하는 값은 두 번째 위치에 반환
    • 분리된 2개의 List 컬렉션은 Pair로 반환됨
  • zip() : 2개의 컬렉션에서 동일한 인덱스 위치한 값끼리 Pair를 만들어 반환함
    • 요소의 개수가 가장 적은 컬렉션에 맞춰 Pair가 구성됨

 

순서 정렬

fun main() {
    val unsortedList = listOf(3, 2, 7, 5)
    println(unsortedList.reversed())  // [5, 7, 2, 3]

    println(unsortedList.sorted())  // [2, 3, 5, 7]

    println(unsortedList.sortedDescending())  // [7, 5, 3, 2]

    println(unsortedList.sortedBy { it % 3 })  // [3, 7, 2, 5]
    println(unsortedList.sortedByDescending { it % 3 })  // [2, 5, 7, 3]
}
  • reversed() : 요소의 순서를 거꾸로하여 반환
  • sorted() : 요소를 작은 수에서 큰 수로 반환하고, 알파벳순으로 정렬한 후 정렬된 컬렉션을 반환
  • sortedBy() : 특정한 비교식에 의해 정렬된 컬렉션을 반환
  • sortedDescending / sortedByDesceding : 요소를 큰 수에서 작은 수로, z부터 a 순서로 정렬해서 반환

 

 

728x90

댓글