Comparable vs Comparator

cutiepazzipozzi·2023년 3월 6일
1

지식스택

목록 보기
2/35
post-thumbnail

아마 옛날에 알고리즘 문제를 풀면서 Comparable에 대해서는 정리한 적이 있을 것이다. 근데 제대로 두 친구들을 비교한 적은 없었던 거 같아서 정확히 기억하고자 작성해본다.

쉽게 생각하면

  • Comparable => 클래스의 기본 정렬을 설정해주는 정렬 인터페이스
  • Comparator => 다른 방식으로 정렬하고 싶을 때 사용하는 정렬 클래스(우리가 흔히 생각하는 오름차순, 내림차순 정렬 말고)

Comparable 인터페이스

class Node implements Comparable<Node> {
	int dest, cost;
	public Node(int dest, int cost) {
    	this.dest = dest;
        this.cost = cost;
    }
    @Override
    public int compareTo(Node n) {
    	return this.cost-n.cost;
    }
}
  • 보통은 위의 경우로 클래스를 선언할 때 정렬을 위한 비교함수 compareTo 사용을 위해 Comparable이 쓰인다.
    (**참고로 Comparable은 java.lang에 내장되어있으며 implement는 인터페이스 상속을 위해 쓰인다!
    -> implements한 클래스는 implements의 내용을 다 사용해야 함)

  • 여기서 제네릭을 Node클래스로 설정한 이유는 비교 대상이 노드 클래스 끼리 비교하는 것이기 때문
    (**Generic은 '일반적'이란 의미로, 특정 타입을 미리 지정하는 것이 아니라 사용자의 필요에 의해 지정하는 일반 타입을 의미한다
    -> 장점! : 타입을 체크하고 변환해줄 필요가 없다 = 관리가 편하다.)

  • compareTo함수를 오버라이딩 하여 정렬 대상을 내가 원하는 변수로 설정해주면 된다! 위의 예시에서는 어떤 노드->목적지 노드로 이동할 때의 가중치를 정렬 기준으로 삼았다.

  • 그래프 탐색 알고리즘 문제를 볼 때, Comparable이 사용된 클래스가 우선순위 큐와 사용되는 경우가 많았다. 무슨 연관이 있는지 궁금했는데 이번에 좀 알 수 있게 됐다.
    우선순위 큐는 옛날에 설명했던 그대로 우선순위가 가장 높은 데이터가 먼저 나오는데, 클래스는 그 안의 변수가 다양하기 때문에 꼭 그 기준을 잡아줘야 한다. 위의 예시처럼 클래스 안에 오버라이딩을 시켜주는 경우가 아니면,

    PriorityQueue<Node> pq = new PriorityQueue<>(priorityQueue.size(), new Comparator<Node>() {
        @Override
        public int compare(Node n1, Node n2) {
           return n1.cost-n2.cost >= 0 ? 1 : -1 
        }
    });

    이렇게 선언할 때 따로 compare함수를 통해 기준을 세워줘도 된다.
    만약 우선순위 큐에 클래스를 집어넣는데 Comparable로 정렬의 기준을 세워주지 않는다면 아래의 오류가 발생한다!
    Exception in thread "main" java.lang.ClassCastException

Comparator 클래스

Arrays.sort(node, new Comparator<Node>() {
	@Override
    public int compare(Node n1, Node n2) {
    	return n1.cost-n2.cost;
    }
    //cost에 관해 내림차순이고 싶다면 return에서 두 객체의 순서 바꿔주면 됨!
});
  • 보통 Arrays.sort()와 함께 쓰여 배열의 정렬 기준을 새로 정립해주는 클래스이다. 주로 익명 클래스로 사용됨!
    (**참고로 Comparator는 java.util에 내장돼있다)

익명 클래스?

'익명' = '이름이 없다' = '기억하지 않아도 된다',
결국은 일시적으로 사용되고 버려지는 객체 !

  • 위의 복잡한 선언 과정을 람다 함수나 stream으로 더 간단하게 대체할 수 있다고 한다! 나중에 한번 사용해보자!
Collections.sort(node, (a, b) -> b.getCost() - a.getCost());

참고

https://m.blog.naver.com/occidere/220918234464
https://velog.io/@hkoo9329/%EC%9E%90%EB%B0%94-extends-implements-%EC%B0%A8%EC%9D%B4
https://cjh5414.github.io/priorityqueue/
https://limkydev.tistory.com/226

profile
노션에서 자라는 중 (●'◡'●)

2개의 댓글

comment-user-thumbnail
2023년 3월 6일

잘 읽고 갑니다!

1개의 답글