Java/Java 문법

[java] 객체 정렬 Comparable과 Comparator

민돌v 2021. 4. 28. 17:14

* C++ 에서 Pair가 있지만, 자바에서는 클래스를 정의해 주어야한다.

1. Comparable<T> 인터페이스

- 자바에서 객체를 정렬하는데 사용되는 메소드인 compareTo() 메소드를 정의하고있는 인터페이스이다.

- 자바에서 같은 타입의 인스턴스를 서로 비교햐야만 하는 클래스들은 모두 Comparable 인텊페이스를 구현하고 있다.

- 따라서 Boolean을 제외한 래퍼 클래스나 String, Time, Date와 같은 클래스의 인스턴스느 모두 정렬이 가능하다.

- 기본 정렬 순서는 "오름차순"이다.

 

< Comparable 예제>

class Car implements Comparable<Car> {
    private String modelName;
    private int modelYear;
    private String color;

    Car(String mn, int my, String c) {
        this.modelName = mn;
        this.modelYear = my;
        this.color = c;
    }

    public String getModel() {
        return this.modelYear + "식 " + this.modelName + " " + this.color;
    }

    public int compareTo(Car obj) {
        if (this.modelYear == obj.modelYear) {
           return 0;
        } else if(this.modelYear < obj.modelYear) { //리턴값이 음수 or 0이면 값이 유지
            return -1;
        } else {
            return 1;  //오름차순
        }
    }
}


public class Comparable01 {
    public static void main(String[] args) {
        Car car01 = new Car("아반떼", 2016, "노란색");
        Car car02 = new Car("소나타", 2010, "흰색");

        System.out.println(car01.compareTo(car02));
    }
}

- CompareTo의 리턴값이 음수 또는 0이면 그대로 유지되고

- 1이면 자리가 바뀐다.

실행 결과

1

<또다른 예제>

// 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) { // y에 대해서는 내림차순
                return 1;
            }
        }
        return -1;
    }
}

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

 


2. Comparator<T> 인터페이스

- Comparable 인터페이스는 기본적으로 오름차순으로 정렬됩니다.

- Comparator 인터페이스는 내림차순이나 다른 기준으로 정렬하고 싶을 때 사용합니다.

- 이때 Comparator 인터페이스를 구현한 클래스에서는 compare() 메소드를 재정의하여 사용하게 됩니다.

*다음 예제는 요소를 내림차순으로 정렬하여 저장하는 TreeSet 인스턴스를 생성하기 위해 Comparator 인터페이스를 구현하는 예제입니다.

 

import java.util.*;

class DescendingOrder implements Comparator<Integer> {
    public int compare(Integer o1, Integer o2) {
        if(o1 instanceof Comparable && o2 instanceof Comparable) {
            Integer c1 = (Integer)o1;
            Integer c2 = (Integer)o2;
            return c2.compareTo(c1);
        }
        return -1;
    }
}

public class Comparable02 {
    public static void main(String[] args) {
        TreeSet<Integer> ts = new TreeSet<Integer>(new DescendingOrder());
  
        ts.add(30);
        ts.add(40);
        ts.add(20);
        ts.add(10);
        
        Iterator<Integer> iter = ts.iterator();
        while(iter.hasNext()) {
            System.out.println(iter.next());
        }
    }

}

실행 결과

40

30

20

10

* Comparator 인터페이스는 다음과 같은 메소드를 사용하여 객체를 정렬합니다.

 

메소드 설명
int compare(T o1, T o2) 전달된 두 객체의 순서를 비교함.
boolean equals(Object obj) 해당 comparator와 전달된 객체가 같은지를 확인함.
default Comparator<T> reversed() 해당 comparator의 역순인 comparator를 반환함.

 

관련 문제

https://blog.naver.com/thalsal/222222468787