빰_s

(25.01.26) Comparator VS Comparable 본문

Java

(25.01.26) Comparator VS Comparable

Job_E 2025. 1. 27. 00:05

자바 사용 중 배열 정렬을 위해 Arrays.sort()를 사용해본 경험이 있을 것이다.

이 메소드는 기본적으로 배열을 크기 기준 오름차순으로 정렬해주는 기능을 가지는데, 때로는 그 역으로 정렬하고 싶거나 자기가 직접 정한 기준으로 정렬을 하고 싶어질 때도 있을 수도 있다.

 

이러한 정렬 로직을 구축할 수 있는 자바의 기능이 제목에 언급된 Comparator와 Comparable라는 인터페이스가 있다.

오늘은 이 두가지 인터페이스를 비교해보도록 하자.

 

1. Comparable

정렬 수행 시 기본적으로 적용되는 정렬 기준이 되는 메소드를 정의하는 인터페이스다.

// Integer class
public final class Integer extends Number implements Comparable<Integer> { ... }
// String class
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { ... }
// 출처 : https://gmlwjd9405.github.io/2018/09/06/java-comparable-and-comparator.html

자바에서 제공되는 정렬이 가능한 모든 클래스들은 Comparable 인터페이스를 사용하고 있으며, 정렬 시에 이에 맞게

정렬이 수행된다.

 

※ 구현 방법

// x좌표가 증가하는 순, x좌표가 같으면 y좌표가 감소하는 순으로 정렬 진행
class Point implements Comparable<Point> {
 int x,y;

@Override
public int compareTo(Point p) {
	if(this.x > p.x) {
		return 1;// x에 대해선 오름차순
	}
	else if(this.x == p.x) {
		if(this.y < p.y) {
			return 1; // y에 대해선 내림차순
		}
	}
	return -1;
	}
}

//main에서의 사용법
List<Point> pointList = new ArrayList<>();
pointList.add(new Point(x,y));
Collections.sort(pointList);

Comparable 인터페이스를 Implement 할 시, 자동으로 @Override로써 주어지는 CompareTo() 메서드를 이용하여 정렬 기능을 구현한다.

즉 CompareTo를 통해 정렬 로직을 커스텀할 수 있고, Collectionms.sort() 등을 사용해서 이를 정렬할 수 있다.

 

CompareTo(T o)를 작성 시 유념해야 할 것은 다음과 같다.

- 하나의 매개변수에는 정렬을 진행할 대상 객체가 들어가며, Collections.sort나 Arrays.sort가 진행된 배열 객체는 CompareTo(T o)의 로직을 따른다.

- 리턴 값이 음수 또는 0이면 객체의 자리가 그대로 유지되며, 양수인 경우엔 두 객체의 자리가 바뀐다.

( 현재 각체 < 파라미터로 넘어온 객체 : 음수 리턴)(※ 기본적으로 오름차순 정렬이므로 아무런 변화가 일어나지 않는다.)

( 현재 겍체 == 파라미터로 넘어온 객체 : 0 리턴)

( 현재 객체 > 파라미터로 넘어온 객체 : 앙수 리턴) (※ 두 객체의 비교 결과가 양수면 두 객체의 위치를 바꾸는 식으로 정렬이 가능하다.)

 

 

2. Comparator : 정렬 가능한 클래스( == Comparable 인터페이스를 구현한 클래스)들의 기본 정렬 기준과 또 다르게 정렬하고 싶을 때 사용하는 인터페이스

 

Comparable 인터페이스는 CompareTo(T o), 매개변수를 대상 객체 자체만 받는 정렬 로직을 사용하는데, Comparator는

Compare(T o1, T o2)의 구조를 가진다. 이는 o1과 o2 이 두 객체의 크기를 비교해서 정렬을 수행한다는 의미가 되며, 여기서 Comparator와 Comparable의 차이가 발생한다.

 

그럼 이번엔 Comparator의 사용법을 알아보자.

//좌표가 증가하는 순, x좌표가 같으면 y좌표가 감소하는 순으로 정렬하라.

class MyComparator implements Comparator<Point> {
@Override
public int compare(Point p1, Point p2) {
	if(p1.x > p2.x) {
		return 1; // x에 대해선 오름차순
	}
	else if(p1.x == p2.x) {
		if(p1.y < p2.y) {
			return 1; //y에 대해선 내림차순
		}
	}
	return -1;
	}
}

//Main에서의 사용법
List<Point> pointList = new ArrayList<>();
pointList.add(new Point(x,y));
MyComparator myComparator = new MyComparator();
Collections.sort(pointList, myComparator); 
//Arrays.sort(), Collections.sort() 메서드는 두번째 인자로 Comparator interface를 받을 수 있다.

 

- 리턴되는 객체가 음수 또는 0이면 객체의 자리가 그대로 유지되며, 양수인 경우엔 두 객체의 자리가 변경된다.

- 첫번째 파라미터가 o1, 두번째 파라미터가 o2라 했을 때

-- o1 < o2 : 음수 리턴

-- o1 == o2 : 0 리턴

-- o1 > o2 : 양수 리턴(정렬 개선 변경 발생)

 

이 두 인터페이스를 이용해 우선순위 큐의 정렬 기준을 변경하거나, 자기 희망사항 대로 정렬을 진행하는 등의 업무가 가능할 것이다.

Comments