본문 바로가기

Language/JAVA

[JAVA] Comparator와 Comparable 이해하기

두 개념을 이해하기 전에 Interface(인터페이스)에 대해 알아야 한다.

 

https://rookie-programmer.tistory.com/186

 

[JAVA] 인터페이스 개념과 장점 쉬운 예시로 이해하기

인터페이스 인터페이스는 구현된 것이 없고, 선언만 있는 메소드로 구성. 즉, 실제 로직이 없는 abstract 메소드의 모음 구현하고자 하는 클래스에서 implements로 받아 기능을 반드시 구현해야 사용

rookie-programmer.tistory.com

인터페이스는 인터페이스는 구현된 것이 없고, 선언만 있는 메소드로 구성. 즉, 실제 로직이 없는 abstract 메소드의 모음으로

자식클래스가 인터페이스를 구현(상속)하려면 반드시 모든 메서드를 overring하여 기능을 구현한다.

 

 

 

💡 Comparable 

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Comparable.html

 

Comparable (Java SE 11 & JDK 11 )

 

docs.oracle.com

Comparable 인터페이스에는 compareTo(T o) 메소드 하나가 선언되어있는 것을 볼 수 있다.

이 말은 우리가 만약 Comparable을 사용하고자 한다면 compareTo 메소드를 구현(재정의)해주어야 한다는 것이다.

compareTo(T o)매개변수가 하나 넘어와서, 자기 자신(this)과 매개변수로 넘어온 객체(o)간의 정렬 관계를 정해준다.

 

 

📌 정렬규칙

this를 더 작은 값 가지는 객체, o를 더 큰 값을 가지는 객체라고 가정한 뒤

this.age에서 o.age를 뺀 값이 음수가 나온다면 o.age 값이 더 큰 것이 맞으니까 오름차순, 양수면 내림차순이 된다

 

(1) 정수형 비교 -> age 변수

오름차순 : this.age - o.age;

내림차순 : o.age - this.age;


(2) 문자열 비교 -> 객체1.compareTo(객체2);

문자열의 자릿수의 차이가 발생할때, 그 문자의 유니코드 값의 차이를 반환하기 때문에 compareTo 함수를 추가적으로 사용해야 한다.

오름차순 : this.name.compareTo(o.name);

내림차순 : o.name.compareTo(this.name);

 

 

사용방법
클래스 : Comparable 인터페이스 implements 후 compareTo메서드 구현
main : Collections.sort(정렬하고자 하는 변수명);

 

[ class ]

class Student implements Comparable<Student>{
    private String name;
    private int age;

    Student(String name, int age) {
        this.age = age;
        this.name = name;
    }
    //기본적으로 extends Object를 하고 있기 때문에 따로 상속관계를 적어주지 않아도
    //toString이 구현되어 있으면 자동으로 객체의 값을 출력해 줌
    //조상 클래스인 Object클래스의 toString을 overriding하여 객체 호출시 자동으로 toString메서드 호출
    @Override
    public String toString(){
        return "이름은 : " + this.name + " 나이는 : " + this.age;
    }

    @Override
    public int compareTo(Student o) {
//        정수형 비교 -> this.age - o.age;
//        문자열 비교 -> this.name.compareTo(o.name);
        return this.name.compareTo(o.name);
    }
}

 

[ main ]

public class C1504ComparableComparator {
    public static void main(String[] args) {
        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student("kim", 22));
        studentList.add(new Student("lee", 25));
        studentList.add(new Student("choi", 20));
        Collections.sort(studentList);
        System.out.println(studentList);
    }
}

 

[ 이름기준 오름차순 정렬결과 ] 

 

 

더보기

아래 방식으로 구현도 가능하다.

Collections.sort(studentList, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return 0;
            }
        });

 

 

 

[Comparable의 특징]

1. 자기 자신과 매개변수를 비교한다.

2. compareTo 메소드를 반드시 구현해야한다.

3. Collections.sort시 매개변수로 정렬하고자 하는 리스트의 변수명 한 개만 넘겨줘야 한다.

 

 

***헷갈리는 부분***

Collections.sort시 매개변수로 리스트와, Comparator 객체까지 넘어오면 Comparator 정렬이다.

List<Student> studentList = new ArrayList<>();
studentList.add(new Student("kim", 22));
studentList.add(new Student("lee", 25));
studentList.add(new Student("choi", 20));
Collections.sort(studentList, Comparator.reverseOrder());
System.out.println(studentList);

 

Collections.sort(studentList, new Comparator<Student>() {
    @Override
    public int compare(Student o1, Student o2) {
        return 0;
    }
});

 

 

 

💡 Comparator 

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Comparator.html#compare(T,T)

 

Comparator (Java SE 11 & JDK 11 )

Compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second. The implementor must ensure that sgn(compare(x, y)) == -sgn(compare(y, x)) for all x and

docs.oracle.com

Comparator인터페이스에는 compare(T o1, T o2) 메소드 하나가 선언되어있는 것을 볼 수 있다.

우리가 만약 Comparable을 사용하고자 한다면 compare 메소드를 구현(재정의)해주어야 한다는 것이다.

compare(T o1, T o2)  매개변수가 두개 넘어와서, 매개변수로 넘어온 객체(o1, o2)간의 정렬 관계를 정해준다.

 

 

📌 정렬규칙

o1를 더 작은 값 가지는 객체, o2를 더 큰 값을 가지는 객체라고 가정한 뒤

o1.age에서 o2.age를 뺀 값이 음수가 나온다면 o2.age 값이 더 큰 것이 맞으니까 오름차순, 양수면 내림차순이 된다

 

(1) 정수형 비교 -> age 변수

오름차순 : o1.age - o2.age;

내림차순 : o2.age - o1.age;


(2) 문자열 비교 -> 객체1.compareTo(객체2);

문자열의 자릿수의 차이가 발생할때, 그 문자의 유니코드 값의 차이를 반환하기 때문에 compareTo 함수를 추가적으로 사용해야 한다.

오름차순 : o1.getName().compareTo(o2.getName());

내림차순 : o2.getName().compareTo(o1.getName());

 

 

사용방법 1
main : 정렬하고자 하는 변수명.sort(new Comparator<클래스명>() {compare메서드 구현}

 

[ class ]

Comparable 방식과 다르게 클래스 안에 implements Comparable, compareTo메서드가 없어야 한다.

class Student{
    private String name;
    private int age;

    Student(String name, int age) {
        this.age = age;
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "이름은 : " + this.name + " 나이는 : " + this.age;
    }

}

 

[ main ]

public class C1504ComparableComparator {
    public static void main(String[] args) {
        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student("kim", 22));
        studentList.add(new Student("lee", 25));
        studentList.add(new Student("choi", 20));
        studentList.sort(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getAge() - o2.getAge();
            }
        });
        System.out.println(studentList);
    }
}

 

[ 나이기준 오름차순 정렬결과 ] 

 

 

 

사용방법 2 - 람다식 사용
main : 정렬하고자 하는 변수명.sort(람다식);

 

[ main ]

public class C1504ComparableComparator {
    public static void main(String[] args) {
        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student("kim", 22));
        studentList.add(new Student("lee", 25));
        studentList.add(new Student("choi", 20));
        studentList.sort((o1, o2) -> o2.getAge() - o1.getAge());
        System.out.println(studentList);
    }
}

 

[ 나이기준 내림차순 정렬결과 ] 

 

 

더보기

사용방법 1을 통해 이름기준으로 오름차순 정렬하는 코드

studentList.sort(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });

 

더보기

사용방법 2를 통해 이름기준으로 오름차순 정렬하는 코드

studentList.sort(((o1, o2) -> o1.getName().compareTo(o2.getName())));

 

응용 - Arrays.sort에 람다식 사용
main : Arrays.sort(배열명, 람다식);

 

[ main ]

String[] strArr = {"hello", "java", "C++", "world2"};
Arrays.sort(strArr, (o1, o2) -> o1.length() - o2.length());

 

[ 글자 길이 수 기준 오름차순 정렬결과 ] 

 

 

 

 

[Comparable의 특징]

1. 두 매개변수 객체를 비교한다.

2. compare 메소드를 반드시 구현해야한다.

 

 

 

 

(+)

Comparator와 Comparable은 클래스 메서드이고, 아래처럼 사용하는 경우에는 인스턴스 객체가 갖고 있는 정렬 메서드이다.
myList.sort(Comparator.naturalOrder());
myList.sort(Comparator.reverseOrder());