본문 바로가기
Development/Kotlin

코틀린(Kotlin) 문법 뽀개기 - 6. Collections란? filter, map, reduce, sort 함수의 사용

by du.it.ddu 2020. 8. 8.
반응형

코틀린의 Collections에 대해 알아보자.

자료구조에 대한 이해가 있다면 좋다.

https://kotlinlang.org/docs/reference/collections-overview.html를 정독하는 것은 더욱 좋다.

위의 공식 문서에서 보면 알 수 있듯, 챕터가 굉장히 많다. 이 포스팅은 Collections가 무엇인지에 대한 간단한 개념과 제공하는 함수를 간단하게 살펴볼 것이다.


위의 링크를 통해 Collections Overview를 보면, 위와 같은 구조를 설명하고 있다.

Iterable과 Collection 인터페이스를 통해 최종적으로 우리가 사용하는 구현체가 List, Set이고 그 외에 Map이 있다. 그리고 MutableList, MutableSet, MutableMap이 있다.

Mutable이 붙은 것과 붙지 않은 것의 차이는 val과 var의 차이를 이해한다면 쉽게 이해할 수 있다. 아래는 예시이다.

fun main() {
    val list: List<String> = listOf(
            "str1", "str2", "str3"
    )

    val mutableList: MutableList<String> = mutableListOf(
            "str1", "str2", "str3"
    )
    
    val set: Set<String> = setOf(
            "str1", "str2", "str3"
    )
    
    val mutableSet: MutableSet<String> = mutableSetOf(
            "str1", "str2", "str3"
    )
    
    val map: Map<Int, String> = mapOf(
            1 to "str1",
            2 to "str2",
            3 to "str3"
    )
    
    val mutableMap: MutableMap<Int, String> = mutableMapOf(
            1 to "str1",
            2 to "str2",
            3 to "str3"
    )
    
    // add가 존재하지 않는다.
    list.add("str4")
    set.add("str4")
    
    // add가 존재한다.
    mutableList.add("str4")
    mutableSet.add("str4")
    
    // put이 존재하지 않는다. map.put(4, "str4")
    map[4] = "str4"
    
    // mutableMap.put(4, "str4")
    mutableMap[4] = "str4"
}

 

위 코드를 보면 알 수 있듯이 list, set은 add 함수가 없고 mutableList, mutableSet은 add 함수가 있다.

또한 map은 put 혹은 map[key] = value 로 값을 할당할 수 없다. 반면 mutableMap은 put 함수 또는 mutableMap[key] = value로 값을 할당할 수 있다.

초기 생성 이후 내부의 데이터를 변경할 수 있느냐에 대한 차이가 있음을 알 수 있다.


이제 Collections를 활용하기 위한 몇 가지 함수를 살펴보자.

이 포스팅에서 살펴 볼 함수는 제목에서 알 수 있듯이 filter, map, reduce, sort이다.

fun main() {
    val list = mutableListOf<CollectionItem>().apply {
        for (i in 0 until 1000) {
            add(CollectionItem())
        }
    }

    val filtered: List<CollectionItem> = list.filter { it.value <= 500 }
    val mapped: List<String> = list.map { it.name }
    val reduced: Int = list
            .map { it.value }
            .reduce { acc, value -> acc + value }

    // list.sortBy { it.value }
    val sorted: List<CollectionItem> = list.sortedBy { it.value }

    val chained: List<Int> = list
            .filter { it.value >= 500 }
            .sortedBy { it.name }
            .map { it.value }
}

class CollectionItem(
        val value: Int = Random().nextInt(1000),
        val name: String = UUID.randomUUID().toString()
) {
    override fun toString(): String {
        return "value = $value, name = $name"
    }
}

 위 코드에 각 함수의 예제를 담아보았다.

CollectionItem은 Int형 value과 String형 name을 갖는다. 값은 임의로 생성하도록 하였고 출력 시 보기 편하기 위해 toString을 오버라이드 했다.

* data class를 사용하면 toString을 오버라이드 하지 않아도 되지만, 현재 블로그에서 다루지 않았었기에 일반 class로 사용하였다. 추후 data class에 대해 포스팅하겠다. 혹은 본인이 알고있다면 data class를 사용해도 된다.

1. filter

filter 함수는 람다의 조건식이 True가 되는 아이템들만을 갖는 리스트로 만들어 준다. 예시에는 filter 함수 뒤에 람다를 통해 "value <= 500" 라는 조건식을 넘겨주었다. 

전체 객체들 중 value가 500 이하인 아이템들만 반환하는 결과를 얻을 수 있다.

filter의 람다의 반환형은 Boolean이 되어야 함을 잊지말자.

filter는 전체 리스트에서 어떤 조건을 만족하는 데이터들로 구성된 리스트를 얻을 때 사용한다. 예를 들면 짝수로만 이루어진 리스트 등이 있겠다.

2. map

map 함수는 람다를 통해 데이터의 형태를 바꾼다. 위의 예제의 mapped의 자료형이 List<String> 인 것이 보이는가? list의 자료형은 List<CollectionItem> 이었으나 map 함수의 람다에 it.name 을 통해 String을 반환한다.

map은 어떤 자료형에서 다른 자료형으로 변경된 리스트를 얻을 때 사용한다.

3. reduce

reduce는 전체 리스트를 하나의 데이터로 모으는 함수다.

위의 reduced는 map을 통해 List<CollectionItem>을 List<Int> 로 우선 바꿔주었다.

그리고 reduce 함수의 람다를 보자. acc는 현재까지 하나로 합쳐진 데이터, value는 다음으로 합쳐질 데이터를 말한다.

화살표 뒤에 acc + value를 통해 값을 합쳐주고 있다. 결국 최종 값은 하나의 Int가 되며 전체 데이터의 value를 합친 값이 된다.

4. sorted

sort 혹은 sorted 함수는 리스트를 정렬한다.

sort는 리스트의 내부를 정렬하기에 새로운 리스트를 만들지 않고 sorted는 정렬된 리스트를 반환한다는 차이가 있다.

sortBy 혹은 sortedBy 뒤의 람다를 통해 어떤 값을 기준으로 정렬하는지를 알려준다.

5. 함수들의 조합

마지막 chained를 보자. filter, sortedBy, map이 엮여있다. 다양한 List를 다루다보면 어떤 데이터를 거르고 이걸 다시 바꾸고 합치는 등등 여러가지 작업을 하게 되는데, 위의 예와 같이 엮어주면 된다.


프로그래밍을 하는 데 있어서 자료구조에 대한 이해는 정말 중요하며 이를 잘 활용하기 위한 함수들을 아는것도 중요하다. (개인적인 의견)

그렇기 때문에 이 예제를 통해 기본적인 개념을 알았다면, 문서를 참고하거나 직접 Collection의 함수들을 살펴보며 공부하는 것을 추천한다. 

반응형