[Java] Comparator VS Comparable
1. Comparable
-
기본적으로 적용되는 정렬 기준이 되는 메서드를 정의하는 인터페이스이다.
-
Comparable 인터페이스를 구현하고 있는 클래스들은 같은 타입의 인스턴스끼지 비교할 수 있는 클래스들이다.
-
Comparable은 java.lang 패키지에 있다.
-
오름차순으로 정렬되도록 구현되어 있다.
public interface Comparable {
public int compareTo(Object o);
}
-
Comparable 인터페이스의 compareTo 메서드는 비교하는 두 객체가 같은면 0, 비교하는 값보다 작으면 음수, 크면 양수를 반환한다.
-
Comparable을 구현하는 클래스들(Integer, String, Data, File)은 기본적으로 오름차순으로 정렬되어 있지만, 내림차순으로 정렬하고 싶은 경우, 반대로 뺄셈하면 된다.
public int compareTo(Integer anotherInteger) {
int thisVal = this.value;
int anotherVal = anotherInteger.value;
return thisVal - anotherVal;
// 삼항연산자를 쓰면 뺄셈보다 성능이 2~3% 더 빠르다.
// return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1 ));
}
- 예시) x좌표가 증가하는 순, x좌표가 같으면 y좌표가 감소하는 순으로 정렬하라.
package me.haeni.string;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Point implements Comparable<Point>{
private int x;
private int y;
public Point(int x,int y)
{
this.x = x;
this.y = y;
}
@Override
public int compareTo(Point o) {
if(this.x > o.x) {
return 1; // x에 대해서는 오름차순
}
else if(this.x == o.x) {
if(this.y < o.y) { // y에 대해서는 내림차순
return 1;
}
}
return -1;
}
public static void main(String[] args) {
List<Point> pointList = new ArrayList<>();
Point first = new Point(9,6);
Point second = new Point(3,4);
Point third = new Point(6,5);
pointList.add(first);
pointList.add(second);
pointList.add(third);
Collections.sort(pointList);
for(Point i:pointList)
{
System.out.println(i.x);
}
}
}
2. Comparator
- 기본 정렬 기준과 다르게 정렬하고 싶을 때 사용하는 인터페이스이다.
- java.util.Comparator
- 주로 익명 클래스로 사용된다.
-
오름차순을 내림차순으로 정렬할 때 많이 사용된다.
- 예시) 내림차순으로 정렬하기
package me.haeni.string;
import java.util.Arrays;
import java.util.Comparator;
public class DescendingSort {
public static void main(String[] args) {
String[] strArr = {"cat", "Dog", "Rabbit", "tiger"};
Arrays.sort(strArr, new Descending());
System.out.println(Arrays.toString(strArr));
}
}
class Descending implements Comparator {
@Override
public int compare(Object o1, Object o2) {
if( o1 instanceof Comparable && o2 instanceof Comparable) {
Comparable c1 = (Comparable) o1;
Comparable c2 = (Comparable) o2;
return c1.compareTo(c2) * -1; // 역순 정렬을 위해 기본 정렬 기준에 -1을 곱한다.
}
// Comparable한 대상이 아니면 -1 반환
return -1;
}
}
-
Comparator interface를 implements한 후, compare() 메서드를 오버라이드한 클래스를 작성한다.
- compare() 메서드 작성방법
- return값이 음수 또는 0이면 자리가 그대로 유지되며, 양수인 경우에는 두 객체의 자리가 변경된다.
- 첫번째 < 두번째 : return 음수
- 첫번째 = 두번째 : return 0
- 첫번째 > 두번째 : return 양수
- Integer.compare(x,y) : 오름차순
- Integer.compare(y,x) : 내림차순
- 사용방법
- Arrays.sort(정렬대상, 정렬기준)
- Collections.sort(정렬대상, 정렬기준)
- 정렬기준으로 Comparator interface를 받을 수 있다.
// 정렬기준은 가변 : Comparator c 대신 정렬 기준만 바꿔주면 된다.
static void sort(Object[] objArr, Comparator c) {
// 정렬 방법은 불변
for(int i =0 ; i<objArr.length-1; i++) {
for(int j =0 ; j<objArr.length-1-i ; j++) {
Object tmp = null;
if(c.compare(objArr[j], objArr[j+1]>0) {
tmp = objArr[j];
objArr[j] = objArr[j+1];
objArr[j+1] = tmp;
}
}
}
}