[Kotlin] Comparable, Comparator

델버·2022년 6월 29일
0

Kotlin

목록 보기
14/18

백준을 풀다가 정렬 문제가 나올 때 Comparable과 Comparator를 활용하는 것을 많이 볼 수 있다. 그렇다면 둘의 차이점은 뭘까?

간단하게 이야기하면 두 가지 모두 객체를 비교할 때 사용한다는 것이 공통점이다. 차이점은 Comparable은 객체 스스로가 정렬 규칙을 갖고 있고 Comparator는 그 정렬 규칙을 정한 객체이다.

만약 Comparable에서 가지고 있는 정렬 규칙 말고 다른 것을 원하면 Comparator를 가져와 쓴다는 것이다. 예시를 보면 이해가 쉽다.

Comparable

  • comparable은 객체 자신이 스스로 정렬 규칙을 갖고있다고 했다. 객체는 Comparable을 상속받아 compareTo를 오버라이드한다.
class Person(var age: Int, var name: String) : Comparable<Person> {
    override fun compareTo(other: Person): Int =
        when {
            this.age > other.age -> 1
            this.age < other.age -> -1
            else                 -> 0
        }
}
  • Person 클래스를 만들었고 거기에 compareTo를 계산한다. 여기서 age로 이 객체 자신과 다른 객체의 값을 비교한다는 규칙이다.
  • 자신 > 다른 → 양수
    자신 < 다른 → 음수
    자신 = 다른 → 0
fun main() {
    val person1 = Person(20, "김민수")
    val person2 = Person(15, "홍영희")
    val person3 = Person(40, "마봉춘")

    println(person1.compareTo(person2)) // 1
    println(person2.compareTo(person3)) // -1
}
  • age로 비교했으므로 자신과 비교 대상의 값을 비교한 결과값을 리턴한다.

Comparator

  • Comparator는 정렬의 규칙인 객체라고 했다.
object SortAge :Comparator<Person> {
    override fun compare(person1: Person, person2: Person): Int {
                return person1.age.compareTo(person2.age)
    }
}
  • age를 기준으로 비교하는 Comparator를 정해줬다.
fun main() {
    val person1 = Person(20, "김민수")
    val person2 = Person(15, "홍영희")
    val person3 = Person(40, "마봉춘")

    listOf<Person>(person1,person2,person3)
        .sortedWith(SortAge)
        .forEach { println("${it.age} ${it.name}") }
}
// 15 홍영희
// 20 김민수
// 40 마봉춘
  • List를 만들어서 sortedWith로 미리 정해둔 규칙인 SortAge를 넘겨줘서 정렬시킨다.
  • Comparator는 규칙를 가지고 있는 객체가 아니라 규칙 자체이고 Comparable은 상속 받으면 규칙을 객체가 가질 수 있게 되는 것이다.

Comparator 활용

  • 그럼 Comparator를 매번 저렇게 길게 적어야 하는가? 댓츠노노. 우리가 잘 익히 알고 있는 람다로 쉽게 넘길 수 있다.
listOf<Person>(person1,person2,person3)
        .sortedWith(Comparator<Person> { person1, person2 ->
            person1.age.compareTo(person2.age)})
        .forEach { println("${it.age} ${it.name}") }
  • Comparator를 람다로 넘겨 규칙을 설정해준다.

  • age뿐만 아니라 name이나 다른 타입과 값도 가능하다.

  • 근데 만약 값이 같은데 이름으로 정렬하고 싶다면 어떻게 할까?

  • 모든 Person의 age를 같게 했다.

fun main() {
    val person1 = Person(15, "김민수")
    val person2 = Person(15, "홍영희")
    val person3 = Person(15, "마봉춘")

    listOf<Person>(person1, person2, person3)
        .sortedWith(Comparator<Person> { person1, person2 ->
            if (person1.age.compareTo(person2.age) == 0) {
                person1.name.compareTo(person2.name)
            } else {
                person1.age.compareTo(person2.age)
            }
        })
        .forEach { println("${it.age} ${it.name}") }
}
  • 조건문으로 만약 자신과 대상이 같으면(0) 다른 값으로 비교하라는 문구를 넣어줬다.

  • 하지만 이것 말고도 thenBy()라는 것으로 설정해줄 수 있는데 그건 다음에 알아보겠다.

0개의 댓글