본문 바로가기
Programming

Effective Kotlin - Respect the contract of compareTo

by 생각하는달팽이 2021. 10. 7.

compareTo의 상호간의 동작 관계

compareTo method 는 Any class 의 함수가 아니고, 코틀린의 오퍼레이터이며, Comparable 인터페이스에 존재한다.
어떤 오브젝트가 해당 interface 를 주입받거나, compareTo 라는 오퍼레이터 함수를 갖고 있다면, 이는 해당 오브젝트가 질서를 갖는다는 의미다.

아래의 질서를 갖는다.

  • 반대칭 : a>= b 이고 b >= a 이면 a == b 입니다. 그러므로, compare 과 equality 사이에는 관계가 있으며, 서로 일치해야 합니다. 일관성이 있어야함.
  • 전이 : a >= b 이고 b >= c 이면 a>=c 이다. 해당 속성이 중요한 이유는 다음 과같은 결론이 이루어지지 않을 경우, 조건 비교가 영원히 진행될 수 있기 때문입니다.
  • Connex : 두 요소는 서로 반드시 관계를 갖는다는 의미입니다. 코틀린에서는 이를 보장해줍니다. compareTo 는 Int 를 리턴하게 되고, 모든 Int 값은 +,-,0 로 리턴됩니다. 두 요소가 관계를 갖고 있지 않는다면, 우리는 정렬 알고리즘을 쓸 수 없기 때문에, 이 속성은 매우 중요합니다.

예제들

  1. surname 정렬
class User(val name: String, val surname: String)
val names = listOf<User>(/*...*/)
val sorted = names.sortedBy { it.surname }
  1. surname 정렬하고 일치하는 경우 name 순으로 정렬
val sorted = names  
.sortedWith(compareBy({ it.surname }, { it.name }))
  1. clsas에 companion object 를 선언해서 사용 ( 외부에서 해다 속성들에 대해 직접 비교하면, 해당 속성에 대해 모호할 수 있으므로 미리 정의해서 사용 )
class User(val name: String, val surname: String) {  
// ...
    companion object {  
    val DISPLAY\_ORDER =  
    compareBy(User::surname, User::name)  
    }  
}

val sorted = names.sortedWith(User.DISPLAY\_ORDER)
  1. Comparable 와 같이 interface 주입
class User(
    val name: String,
    val surname: String
) : Comparable<User> {
    override fun compareTo(other: User): Int =
        compareValuesBy(this, other,
            { it.surname },
            { it.name }
        )
}
반응형