[Java] 8. 제네릭-`Comparable` 와 `Comparator` 인터페이스(feat. Collections sort())


제네릭 포스팅의 연장선으로 Comparable<T>Comparator<T> 인터페이스를 구현하여 java 정렬 방법으로 java.util.Collections 클래스의 sort()를 이용한 정렬 포스팅이다.


해당 포스팅에는 이 외에 LocalDate 비교와 Ramdom 메서드 짧은 예제 코드도 포함하고 있다.



1. Collections.sort()

제네릭 포스팅의 연장선으로 Comparable<T>Comparator<T> 인터페이스를 구현하여 java 정렬 방법으로 java.util.Collections 클래스의 static 메소드인 sort()를 이용해 정렬을 한다.

List<User> userList = getUserList();
Collections.sort(userList);

아래 Collections 클래스의 sort() 메서드를 보면 타입이나 메서드에서 <? super T> 제네릭 와일드 카드의 하한 제한으로 T와 그 조상들만 가능하게 제한을 두고 있다.


Collections 클래스 sort()

Modifier and TypeMethod
static <T extends Comparable<? super T>> voidsort(List<T> list)
static <T> voidsort(List<T> list, Comparator<? super T> c)



2. Comparable<T>Comparator<T> 인터페이스

Collections 의 sort() 메서드를 통해 특정 필드를 사용자정의로 정렬을 하려면
아래 표에 Comparable<T>Comparator<T> 인터페이스를 이용해서
메서드를 오버라이드헤서 구현하면 된다.


Comparable<T> 와 Comparator<T> 간단비교

  • Comparable<T>Comparator<T> 
    Packagejava.langjava.util
    MethodcompareTo​(T o)compare​(Object o1, Object o2)
    비교대상자기자신두 객체


아래는 사용방법에 대한 스케치(?) 코드이다. 더 밑에는 전체 예제 코드와 주석이 있으며, 해당 포스팅 내용은 이걸로 끝이다.



1) Comparable<T> 인터페이스의 compareTo() 오버라이드

static <T extends Comparable<? super T>> void
List<User> userList = getUserList();
Collections.sort(userList);
@Override
public int compareTo(User u) {
    //a > b : 양수를 반환
    //a < b : 음수를 반환
    //a == b : 0을 반환
    return 구현;
}



2) 인터페이스의 compare() 오버라이드

static <T> void
List<User> userList = getUserList();
Collections.sort(userList, new User());
@Override
public int compare(User u1, User u2) {
    //a > b : 양수를 반환
    //a < b : 음수를 반환
    //a == b : 0을 반환
    return 구현;
}



3. 전체 예제 코드

해당 예제코드는 추가로 LocalDate 비교와 Ramdom 메서드 짧은 예제 코드도 포함하고 있다.

class User implements Comparable<User>, Comparator<User> {

    private int id;
    private String name;
    private int point;
    private LocalDate joinDt;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPoint() {
        return point;
    }

    public void setPoint(int point) {
        this.point = point;
    }

    public LocalDate getJoinDt() {
        return joinDt;
    }

    public void setJoinDt(LocalDate joinDt) {
        this.joinDt = joinDt;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", point=" + point +
                ", joinDt=" + joinDt +
                "}\n";
    }

    //Comparable 인터페이스의 compareTo 오버라이드
    @Override
    public int compareTo(User u) {
        //a > b : 양수를 반환
        //a < b : 음수를 반환
        //a == b : 0을 반환
        if (this.point > u.point) return 1;
        else if (this.point < u.point) return -1;
        else return 0;
    }

    //Comparator 인터페이스의 compare 오버라이드
    @Override
    public int compare(User u1, User u2) {
        LocalDate u1JoinDt = u1.getJoinDt();
        LocalDate u2JoinDt = u2.getJoinDt();
        //compareTo ReturnValue
        //a > b : 양수를 반환
        //a < b : 음수를 반환
        //a == b : 0을 반환
        return u1JoinDt.compareTo(u2JoinDt);
    }

    //내부클래스로 Comparator 인터페이스의 compare 오버라이드
    static class UserIdOrderByDesc implements Comparator<User> {

        @Override
        public int compare(User u1, User u2) {
            //a > b : 양수를 반환
            //a < b : 음수를 반환
            //a == b : 0을 반환
            if (u1.getId() > u2.getId()) return 1;
            else if (u1.getId() < u2.getId()) return -1;
            else return 0;
        }
    }
}

public class ExGenericCollections {

    public static void main(String... args) {

        List<User> userList = getUserList();
        //Point 로 Comparable 이용한 정렬
        Collections.sort(userList);
        System.out.println(userList);

        //JoinDt 로 Comparator 이용한 정렬
        Collections.sort(userList, new User());
        System.out.println(userList);

        //Id 로 내부클래스의 Comparator 이용한 정렬
        Collections.sort(userList, new User.UserIdOrderByDesc());
        System.out.println(userList);

    }

    public static List<User> getUserList() {

        List<User> userList = new ArrayList<User>();
        User user = new User();

        for (int i = 0; i<20; i++) {
            user = new User();
            user.setId( getRandomUserId() );
            user.setName( getRandomName() );
            user.setPoint( getRandomPoint() );
            user.setJoinDt( getRandomJoinDt() );
            userList.add( user );
        }

        return userList;
    };


    public static int getRandomUserId() {
        return new Random().nextInt(10000);
    }

    public static int getRandomPoint() {
        int min = 1000;
        return new Random().nextInt(1000) + min;
    }

    public static String getRandomName() {
        return getName();
    };

    public static LocalDate getRandomJoinDt(){
        Random r = new Random();
        return LocalDate.of(r.nextInt(20) + 2000, r.nextInt(11) + 1, r.nextInt(28) + 1);
    }


    public static String getName() {

        String[] firstNameArr = {
                "김"
                , "이"
                , "박"
                , "최"
                , "정"
                , "안"
                , "강"
        };
        String[] lastNameArr = {
                "민준"
                , "서준"
                , "도윤"
                , "예준"
                , "시우"
                , "하준"
                , "주원"
                , "지호"
                , "지후"
                , "준우"
                , "준서"
                , "건우"
                , "도현"
                , "현우"
                , "서연"
                , "서윤"
                , "지우"
                , "서현"
                , "하은"
                , "하윤"
                , "민서"
                , "지유"
                , "윤서"
                , "지민"
                , "채원"
                , "수아"
                , "지아"
                , "지윤"
                , "은서"
        };

        int r1 = new Random().nextInt(7);
        int r2 = new Random().nextInt(30);
        String n1 = firstNameArr[r1];
        String n2 = lastNameArr[r1];

        return n1 + n2;
    }
}