백준을 풀다가 정렬 문제가 나올 때 Comparable과 Comparator를 활용하는 것을 많이 볼 수 있다. 그렇다면 둘의 차이점은 뭘까?
간단하게 이야기하면 두 가지 모두 객체를 비교할 때 사용한다는 것이 공통점이다. 차이점은 Comparable은 객체 스스로가 정렬 규칙을 갖고 있고 Comparator는 그 정렬 규칙을 정한 객체이다.
만약 Comparable에서 가지고 있는 정렬 규칙 말고 다른 것을 원하면 Comparator를 가져와 쓴다는 것이다. 예시를 보면 이해가 쉽다.
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
}
}
fun main() {
val person1 = Person(20, "김민수")
val person2 = Person(15, "홍영희")
val person3 = Person(40, "마봉춘")
println(person1.compareTo(person2)) // 1
println(person2.compareTo(person3)) // -1
}
object SortAge :Comparator<Person> {
override fun compare(person1: Person, person2: Person): Int {
return person1.age.compareTo(person2.age)
}
}
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 마봉춘
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()라는 것으로 설정해줄 수 있는데 그건 다음에 알아보겠다.