Primitive type(int, float, double)의 경우 부등호로 두 변수 비교가 가능하다. 그렇다면 객체 비교는 어떻게 할까?
객체는 비교기준이 따로 없기 때문에 기준을 정해줘야한다. 이는 Comparable와 Comparator를 통해 해결할 수 있다.
Comparable와 Comparator는 인터페이스로 구현 시 메소드 오버라이딩을 반드시 해줘야한다.
Comparable 인터페이스는 다음과 같이 정의되어 있다.
public interface Comparable<T> {
public int compareTo(T o);
}
Comparable은 Java.lang package에 있어 import할 필요가 없으며 구현 시 반드시 compareTo(T o) 메소드를 재정의해야한다. compareTo(T o) 메소드는 매개변수가 한 개로 "자기 자신과 매개변수 객체를 비교"한다.
Comparator 인터페이스에 선언된 많은 메소드 중 정렬 시 구현해야하는 메소드는 다음과 같다.
public interface Comparator<T> {
int compare(T o1, T o2);
}
Comparator는 Java.util package에 있어 import 해줘야하며 구현 시 반드시 compareTo(T o1, T o2) 메소드를 재정의해야한다. Comparator(T o1, T o2) 메소드는 두 개의 매개변수를 필요로 하며 "두 매개변수 객체를 비교"한다.
public class SortEx {
public static void main(String[] args) {
Student[] student = new Student[4];
student[0] = new Student("길록", 20140151, 3.5);
student[1] = new Student("이후배", 20150001, 4.5);
student[2] = new Student("강선배", 20110001, 3.5);
student[3] = new Student("홍회장", 20130001, 2.8);
System.out.println("==== 정렬 전 ====");
for (Student s : student) {
System.out.println(s.toString());
}
System.out.println();
Arrays.sort(student); // 학번을 기준으로 오름차순 정렬
System.out.println("==== 정렬 후 ====");
for (Student s : student) {
System.out.println(s.toString());
}
System.out.println();
Arrays.sort(student, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
double s1Score = o1.score;
double s2Score = o2.score;
if (s1Score == s2Score) { // 학점이 같으면
return Double.compare(o1.stuNo, o2.stuNo); // 학번 오름차순
}
return Double.compare(s2Score, s1Score); // 학점 내림차순
}
});
System.out.println("==== 학점 추가 정렬 ====");
for (Student s : student) {
System.out.println(s.toString());
}
}
}
class Student implements Comparable<Student> {
String name; // 이름
int stuNo; // 학번
double score; // 학점
public Student(String name, int stuNo, double score) {
this.name = name;
this.stuNo = stuNo;
this.score = score;
}
@Override
public int compareTo(Student o) {
// 학번을 기준으로 오름차순 정렬
// if (this.stuNo > o.stuNo) {
// return 1;
// } else if (this.stuNo < o.stuNo) {
// return -1;
// } else {
// return 0;
// }
return this.stuNo - o.stuNo;
}
@Override
public String toString() {
return "이름 : " + name + ", 학번 : " + stuNo + ", 학점 : " + score;
}
}
첫 번째 출력결과는 정렬 전으로 저장순서대로 출력되었다.
두 번째 출력결과는 학번을 기준으로 오름차순 정렬하였으며 Arrays.sort() 시 compareTo 메소드를 호출해서 기준정렬에 따라 정렬된 것을 의미한다.
마지막 출력결과는 학점이 같을 경우 학번을 오름차순으로 정렬하고 그렇지 않을 경우에는 학점을 내림차순으로 정렬한 것을 의미한다. 정렬 시 사용된 Double.compare()는 Double 객체에서 제공하는 메소드로 실수값을 비교할 수 있다.
Comparator의 compare() 메소드를 사용하기 위해 implements해서 메소드를 재정의할 수 있지만 익명 객체(클래스)를 사용해서 Comparator의 비교 기능을 사용할 수 있다.
변수와 메소드를 선언하며 다른 클래스로부터 상속받거나 인터페이스를 구현하는 일반적인 클래스와 달리 익명 클래스는 클래스 선언과 객체 생성을 동시에 하며, 오직 하나의 객체만을 생성하는 일회용 클래스이다. 또한 단 하나의 클래스를 상속받거나 단 하나의 인터페이스만을 구현할 수 있다.
new 부모클래스이름() {
// 멤버 선언
}
또는
new 구현인터페이스이름() {
// 멤버 선언
}
Comparable은 기본 정렬기준 구현 시 사용하고, comparator는 기본 정렬기준 외에 다른 기준으로 정렬 시 사용한다.