Comaparator와 Comparable은 “객체를 비교할 수 있도록” 만들어주는 인터페이스
Comparable 이란
“자기 자신과 매개변수 객체를 비교”
compareTo(Type o)의 매개변수와 자기 자신을 비교
"주의할 점" ( 절대 강조 )
사실 우리가 편리하게 두 수의 대소비교를 두 수의 차를 통해 음수, 0, 양수로 구분하여 구했지만, 여기에는 치명적인 단점이 있다. 바로 뺄셈 과정에서 자료형의 범위를 넘어버리는 경우가 발생할 수 있기 때문이다.
일단 위 예시에선 int형으로 살펴보았으니 이를 예로 들겠다.
먼저 int형의 범위가 어떤지를 파악해야 한다.
int 자료형은 32비트(4바이트) 자료형이며 표현 범위가 -231 ~ 231-1 으로, 이를 풀어쓰면 -2,147,483,648 ~ 2,147,483,647 이다.
만약 해당 범위 밖을 넘게 되면 반대편의 값으로 넘어가게 된다.
쉽게 말하자면 -2,147,483,648 - 1 = -2,147,483,649 일 것이다. 하지만, int 자료형에서 표현할 수 없는 수로 2,147,483,647으로 int형의 최댓값으로 반환한다. 이렇게 주어진 범위의 하한선을 넘어버리는 것을 'Underflow' 라고 한다.
반대로 2,147,483,647 + 1 = 2,147,483,648 일 것이다. 하지만 마찬가지로 int 자료형에서 표현할 수 없는 수로 -2,147,483,648 이 되어 int 형의 최솟값으로 반환된다. 이렇게 주어진 범위의 상한선을 넘어버리는 것을 'Overflow' 라고 한다.
Comparator 이란
“두 매개변수 객체를 비교”
compare(Type o1, Type o2)의 두 매개변수를 비교
그리고 여기서도 마찬가지로 ubderflow, overflow 주의!
Comparator 예 - 백준 10814
package BOJ;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;
public class BOJ10814 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
int num = Integer.parseInt(br.readLine());
Node[] arr = new Node[num];
for(int i=0; i<num; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
arr[i] = new Node(Integer.parseInt(st.nextToken()), st.nextToken());
}
Arrays.sort(arr, new Comparator<Node>() {
@Override
public int compare(Node o1, Node o2) {
return o1.age - o2.age;
}
});
for(int i=0; i<arr.length; i++) {
sb.append(arr[i].age).append(" ").append(arr[i].name).append("\n");
}
System.out.println(sb);
}
static class Node{
int age;
String name;
public Node(int age, String name) {
this.age = age;
this.name = name;
}
}
}
JavaScript
복사
→ age값을 비교해서 정렬하므로 name에 대해선 “Stable 속성”이 적용
[두 수의 비교 결과에 따른 작동 방식]
음수일 경우 : 두 원소의 위치를 교환 안함
양수일 경우 : 두 원소의 위치를 교환 함