자바에서 정렬에 관련된 작업을 할 경우 떠올릴 수 있는 대표적인 인터페이스가 두가지 있다.

Comparator와 Comparable이다.

두 가지 인터페이스의 차이점과 사용법에 대해 알아보자.

 

두 인터페이스가 사용되는 이유는 공통적이다.

Primitive 타입의 숫자나 문자를 비교할 경우 명확한 기본 비교로직이 존재한다. 오름차순이라면 '1'보단 '2'가 크고, '가' 보다는 '나'가 크다. 하지만 비교하는 대상이 객체라면 기본 비교로직으로는 비교가 불가능하다.

예를들어 Game 클래스로 만든 객체들을 정렬한다고 가정한다면 여러가지 정렬을 위한 기준이 있을 수 있다. (발매년도, 타이틀명 등등) 이 때, 정렬 기준에 대한 명확한 로직을 정의할 수 있도록 도와주는 것이 Comparator와 Comparable 인터페이스이다. 

 

하나씩 살펴보자.

 

Comparator

'비교기'라는 이름에서 알 수 있듯이 비교를 위한 보조로직을 따로 작성하여 정렬시 인자로 건네준다.

보조로직 작성은 Comparator의 int compare(obejct args1, object args2) 메서드에 작성한다.

리스트의 정렬은 Collections.sort() 메서드를 사용하는데, 여기의 인자로 전달한다.

public class GameComparatorTest {
    @Test
    public void test1(){
        Comparator<Game> gameComparator = new Comparator<Game>() {
            // 비교를 위한 로직을 작성
            public int compare(Game game1, Game game2) {
                // 발매년도는 내림차순으로 하면서, 같은 발매년도에서는 타이틀명을 오름차순으로 하고싶다.
                if(game1.year != game2.year){
                    return Integer.compare(game1.year, game2.year) * (-1);
                }else {
                    return game1.title.compareTo(game2.title);
                }
            }
        };
 
        List<Game> games = new ArrayList<>();
        games.add(new Game(2000"Assassin Creed"));
        games.add(new Game(1990"Overwatch"));
        games.add(new Game(2000"League Of Legends"));
        games.add(new Game(1990"A Power"));
 
        Collections.sort(games, gameComparator);
 
        System.out.println(games);
    }
}
 
class Game {
    int year;
    String title;
 
    public Game(int year, String title) {
        this.year = year;
        this.title = title;
    }
 
    @Override
    public String toString() {
        return "Game{" +
                "year=" + year +
                ", title='" + title + '\'' +
                '}';
    }
}

// 출력결과

[Game{year=2000, title='Assassin Creed'}, Game{year=2000, title='League Of Legends'}, Game{year=1990, title='A Power'}, Game{year=1990, title='Overwatch'}]

발매년도로 내림차순 되었고, 발매년도가 같은경우 타이틀명으로 오름차순 되었다. 

 

 

Comparable

Comparator와 유사하게 비교를 위한 보조로직을 정의하지만 작성하는 위치가 다르다. '비교할 수 있는'이라는 뜻과 같이 비교하고자 하는 클래스에 비교로직을 정의한다. 마찬가지로 Collections.sort() 메서드로 정렬할 수 있고 이 때는 두번째 인자가 필요하지 않는다.

public class GameComparableTest {
    @Test
    public void test1(){
        List<Game> games = new ArrayList<>();
        games.add(new Game(2000"Assassin Creed"));
        games.add(new Game(1990"Overwatch"));
        games.add(new Game(2000"League Of Legends"));
        games.add(new Game(1990"A Power"));
 
        Collections.sort(games);
 
        System.out.println(games);
    }
}
 
class Game implements Comparable<Game> {
    int year;
    String title;
 
    public Game(int year, String title) {
        this.year = year;
        this.title = title;
    }
 
    @Override
    public String toString() {
        return "Game{" +
                "year=" + year +
                ", title='" + title + '\'' +
                '}';
    }
 
    @Override
    public int compareTo(Game game1) {
        // 발매년도는 내림차순으로 하면서, 같은 발매년도에서는 타이틀명을 오름차순으로 하고싶다.
        if(this.year != game1.year){
            return Integer.compare(this.year, game1.year) * (-1);
        }else {
            return this.title.compareTo(game1.title);
        }
    }
}

출력결과는 Comparator의 출력결과와 동일하다.

 

즉, 두 가지 인터페이스 모두 객체 비교를 위한 보조로직을 정의하는데 사용되는 인터페이스이다. 상황에 맞게 선택하여 사용하자.

 

 

 

 

'개발 > JAVA' 카테고리의 다른 글

JVM, JRE, JDK 간단 개념  (0) 2020.12.07
ExecutorService 사용법  (0) 2020.12.01
LocalDateTime, ZonedDateTime  (0) 2019.10.11
Collections를 이용한 정렬(sort method) 활용  (0) 2017.05.09
BigDecimal & BigInteger  (0) 2017.04.18

+ Recent posts