Comparable와 Comparator

Eunkyung·2021년 10월 29일
0

Java

목록 보기
10/21

Primitive type(int, float, double)의 경우 부등호로 두 변수 비교가 가능하다. 그렇다면 객체 비교는 어떻게 할까?
객체는 비교기준이 따로 없기 때문에 기준을 정해줘야한다. 이는 Comparable와 Comparator를 통해 해결할 수 있다.
Comparable와 Comparator는 인터페이스로 구현 시 메소드 오버라이딩을 반드시 해줘야한다.

Comparable

Comparable 인터페이스는 다음과 같이 정의되어 있다.

public interface Comparable<T> {
	public int compareTo(T o);
}

Comparable은 Java.lang package에 있어 import할 필요가 없으며 구현 시 반드시 compareTo(T o) 메소드를 재정의해야한다. compareTo(T o) 메소드는 매개변수가 한 개로 "자기 자신과 매개변수 객체를 비교"한다.

Comparator

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) 메소드는 두 개의 매개변수를 필요로 하며 "두 매개변수 객체를 비교"한다.

Comparable, Comparator 예제


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 구현인터페이스이름() {
	// 멤버 선언
}

Summary

Comparable은 기본 정렬기준 구현 시 사용하고, comparator는 기본 정렬기준 외에 다른 기준으로 정렬 시 사용한다.

Reference

profile
꾸준히 하자

0개의 댓글