Chapter 5

15452 단어 kotlinkotlin

kotlin-in-action

  • 5장
    • 람다식
      : 다른 함수에 넘겨주는 코드 조각
      자바에서와 마찬가지로 어떤 식이나 인스턴스를 매개변수로 넘겨줄때, 과거엔 익명 클래스를 사용해서 처리했지만 코드를 더 간결하게 만들기 위해 람다식이 필요해졌다.
      또한 컬렉션을 다룰때에도 고전적인 방법의 코드로는 반복문과 조건문의 반복된 코드로 처리해야되서 코드가 길어지지만 람다식을 사용하면 상당히 간추릴 수 있다.
      아래에는 사람 리스트가 있고 그 중에서 최고 연장자를 찾는 로직이다.
      • 람다식을 쓰지 않은 기존 방식

        fun findTheOldest(people: List<Person>) {
            var maxAge = 0
            var oldest = Person? = null
            
            for (person in people) {
                if (person.age > maxAge) {
                    maxAge = person.age
                    oldest = person
                }
            }
        }
      • 람다식을 쓴 방식

        val people = listOf(Person("Alice", 20), Person("Bob", 30))
        println(people.maxBy { it.age }) // maxBy 만으로 비교해서 최고 연장자 추려냄
        // maxBy 는 컬렉션에서 제공되는 기본 메소드
        
        // 혹은 아래와 같이도 가능
        people.maxBy(Person::age)
      • 람다식 문법
        : 코틀린에서의 람다식은 중괄호를 기반으로 작성된다.

        val sum = { x: Int, y: Int -> x + y }
        println(sum(1, 2)) // 3

        코드의 일부 블록을 중괄호로 감싸서 실행한다면 run 키워드를 쓴다

        run { println(1) } // 다만 이런식의 코드는 쓰지 않는게 일반적

        위의 maxBy 예제를 이런식으로 작성하기도 한다

        people.maxBy { p: Person -> p.age }
        people.maxBy { p -> p.age }

        p -> p.age 와 같이 타입을 생략하는 것은 컴파일러가 추론을 할 수 있기 때문이다.
        위의 it.age 에서 it 은 람다식에서 쓰이는 기본 파라미터 이름이라고 한다. (자동 생성된 파라미터 이름)
        (람다 안에 람다 식이 중첩된 케이스라면 it 을 쓰지 않는게 더 가독성을 높인다)

      • 변수 포획
        : 람다식이 사용된 메소드 내에서 쓰이는 람다식의 외부 변수를 사용하는 것을 변수를 포획한다고 부른다.

        fun printProblemCounts(responses: Collection<String>) {
            var clientErrors = 0
            var serverErrors = 0
            
            responses.forEach {
                if (it.startsWith("4")) {
                    clientErrors++
                } else if (it.startsWith("5")) {
                    serverErrors++
                }
            }
        }

        위와 같이 람다식 밖에 존재하는 clientErrors, serverErrors 변수를 가져와서 사용할 수 있는데 이때의 두 외부 변수를 람다가 포획한 변수라 부른다

      • 멤버 참조
        자바와 마찬가지로 함수를 참조하거나 객체의 멤버를 참조하는 경우 :: 를 이용해서 람다식 대신 처리가 가능하다

        val getAge = Person::age
        people.maxBy(Person::age)

        최상위에 선언한 함수를 참조하는 경우 이름을 생략하고 바로 참조하는 케이스도 존재한다

        val action = { person: Person, message: String ->
            sendEmail(person, message)
        }
        val nextAction = ::sendEmail
    • 컬렉션 관련 함수들
      : java 8 이후로 나온 함수랑 똑같다.
      1. filter, map

        val list = listOf(1, 2, 3, 4) 
        println(list.filter { it % 2 == 0 }) // 2, 4
        
        println(list.map { it * it }) // 1, 4, 9, 16
      2. all, any, count, find

        val canBeInClub27 = { p: Person -> p.age <= 27 }
        
        val people = listOf(Person("Alice", 27), Person("Bob", 31))
        
        println(people.all(canBeInClub27)) // false
        
        println(people.any(canBeInClub27)) // true
        
        println(people.count(canBeInClub27)) // 1
        
        println(people.find(canBeInClub27)) // Person(name=Alice, age=27)
      3. groupBy

        val people = listOf(Person("Alice", 31), Person("Bob", 29), Person("Carol", 31))
        
        println(people.groupBy { it.age })
        // {29=[Person(name=Bob, age=29)], 31=[Person=(name=Alice, age=31), Person(name=Carol age=31)]}}
      4. flatMap, flatten

        val strings = listOf("abc", "def")
        println(strings.flatMap { it.toList() }) // [a, b, c, d, e, f]

        // 2/17

좋은 웹페이지 즐겨찾기