본문 바로가기
언어/JAVA

[JAVA] Comparable [compareTo()] 와 Comparator [compare()]의 차이점

by chan10 2021. 3. 2.

자바에서는 정렬을 하기 위해 기본적으로 두 가지 인터페이스를 제공해 주는데 

 

이 인터페이스들이 바로 Comparable와 Comparator입니다.

 

모두 인터페이스 모두 정렬에 필요한 메서드를 정의함으로써 정렬을 위해 사용하는 목적은 동일합니다.

Comparable [compareTo()] - 인터페이스를 구현한 객체의 기본 정렬기준을 구현하는데 사용.

Comparator [compare()] - 기본 정렬기준 외에 다른 기준으로 정렬하고자 할 때 사용

 

Comparable [compareTo()]

정의

  o Comparable 인터페이스는 대게 객체 간의 비교 시 기본적인 정렬 기준을 정의할 때 사용합니다.

  o 클래스(객체)에 직접 Comparable인터페이스를 구현 후 compareTo() 메서드를 오버라이딩 함으로써 객체끼리 비교 시 어떤 기준으로 정렬할 것인지를 정의합니다. 이를 기본 정렬기준이라고 하며 클래스 내에 하나만 가질 수 있습니다.

  o 정렬하는 기준에 따라서 기본정렬 오름차순 / 내림차순이 정해집니다.

  o 기본 정렬기준 없이 객체 정렬을 시도하는 경우 정렬을 할 기준이 없기에 예외가 발생합니다.

  o 비교 타입은 서로 같은 타입이 아니어도 가능합니다. (ex Person, Animal)

  o 자바에서 제공되는 정렬이 가능한 클래스들은 모두 Comparable 인터페이스를 구현하고 있으며 Comparable은 구현하고 있는 클래스는 같은 타입의 인스턴스끼리 서로 비교할 수 있습니다.

  o 기본적으로 Integer, Double와 같은 wrapper 클래스는 오름차순, String클래스는 사전순으로 정렬이 제공됩니다.

  o TreeSet에 Integer인스턴스를 저장했을 때 정렬되는 기준도 compareTo메서드에 의한 것입니다.

 

사용 메서드

  Array.sort(array)

  Collections.sort(list)

 

구현 방법

  1. 정렬할 클래스(객체)에 Comparable 인터페이스 구현 및 compareTo() 메서드 오버라이딩을 해준다.

  2. 정렬의 기준의 될 멤버를 사용하여 아래 형식으로 return값을 반환할 수 있도록 작성한다.

      멤버 변수 - 매개변수 멤버 = return 양수 -> 오름차순 정렬 (>)

      멤버 변수 - 매개변수 멤버 = return 0 -> 변화 없음 (==)

      멤버 변수 - 매개변수 멤버 = return 음수 -> 내림차순 정렬 (<)

  3. 이 때 사용된 변수 값이 객체 정렬의 기준값이 되며 return 값에 따라 오름차순/내림차순 정렬이 결정된다.

 

  - 반환문 작성은 비교하는 값이 String 타입인 경우 String클래스의 compareTo() 메서드를 사용하며

  - 비교하는 값이 숫자 타입인 경우 주로 -(뺄셈)한 값을 return 합니다. 

    (Integer.compare()나 if로 위 반환형식에 맞게 사용할 수도 있습니다.)

 

구현 예시

public class ProjectTest
 public static void main(String[] args)
         ArrayList<Student> st = new ArrayList<Student>();
         st.add(new Student("김길동",20));
         st.add(new Student("박길동",32));
         st.add(new Student("홍길동",16));
         
         // Comparable 오름 차순 정렬 (이름)
         Collections.sort(st);    
         System.out.println("Comparable(Asc) : "+st);
 
 
class Student implements Comparable<Student>
    @Override
    public int compareTo(Student o) {
        return name.compareTo(o.name);
    }
결과
Comparable(Asc) : [[김길동, 20], [박길동, 32], [홍길동, 16]]

 

Comparator [compare()]

정의

  o Comparator 인터페이스는 Comparable에서 정의한 기본 정렬 기준 외에 다른 기준으로 객체를 정렬하려고 할 때 사용하는 인터페이스입니다.

  o Comparable인터페이스와 달리 정렬의 기준이 될 클래스를 별도로 생성하거나 익명 클래스를 생성합니다.

     생성한 클래스를 객체를 정렬할 기준으로 제공 함으로써 작성된 기준에 맞게 정렬됩니다.

  o Comparator는 서로 같은 타입끼리만 비교가 가능합니다.

  o 기본적으로 제공되는 정렬 메소드(Array,Collections)는 오름차순으로 동작하기에 주로 내림차순을 정의할 때 사용됩니다.

 

사용 메서드

  Array.sort(array,new Comparator)

  Collections.sort(list,new Comparator)

  Comparator가 구현된 객체를 두 번째 인자값으로 받으며 구현된 정렬 방법에 따라 객체가 정렬된다.

 

구현 방법

  1. 정렬할 클래스(객체)에 Comparator 인터페이스 구현 및 compare()메소드 오버라이딩을 해준다.

  2. 정렬의 기준의 될 멤버를 사용하여 아래 형식으로 return값을 반환할 수 있도록 작성한다.

      멤버 변수 - 매개변수 멤버 = return 양수 -> 오름차순 정렬 (>)

      멤버 변수 - 매개변수 멤버 = return 0 -> 변화 없음 (==)

      멤버 변수 - 매개변수 멤버 = return 음수 -> 내림차순 정렬 (<)

  3. 이 때 사용된 변수 값이 객체 정렬의 기준값이 되며 return 값에 따라 오름차순/내림차순 정렬이 결정된다.

 

(Comparable와 동일)

  - 반환문 작성은 비교하는 값이 String 타입인 경우 String클래스의 compareTo() 메서드를 사용하며

  - 비교하는 값이 숫자 타입인 경우 주로 -(뺄셈)한 값을 return 합니다. 

    (Integer.compare()나 if로 위 반환형식에 맞게 사용할 수도 있습니다.)

 

구현 예시

public class ProjectTest
 public static void main(String[] args)
         ArrayList<Student> st = new ArrayList<Student>();
         st.add(new Student("김길동",20));
         st.add(new Student("박길동",32));
         st.add(new Student("홍길동",16));
         
        // Comparator 내림차순 정렬 (이름)
         Collections.sort(st,new StudentSort());    
         System.out.println("Comparator(Desc) : "+st);
 
class Student {...}
 
class StudentSort implements Comparator<Student>
    @Override
    public int compare(Student s1, Student s2) {
        return s2.name.compareTo(s1.name);
    }
결과
Comparator(Desc) : [[홍길동, 16], [박길동, 32], [김길동, 20]]

 

정리

  o Comparable인터페이스와 Comparator인터페이스는 구현하는 인터페이스와 사용법만 약간 다를 뿐 비교하는 기능은 같습니다.

  o Comparable인터페이스 : 비교 대상 객체 , Comparator인터페이스 : 기준이 될 클래스를 별도로 구현

  o 문자열이나 정수형 비교 시 각 클래스에서 구현된 compare(), compareTo()메서드를 사용합니다.

     (이는 해당 클래스에서 Comparable, Comparator인터페이스를 구현하고 있다는 의미입니다.)

  o 기본적으로 정수형은 오름차순으로, 문자열은 유니코드를 기반으로 사전순 정렬합니다.


전체 코드

package test.project;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
 
public class ProjectTest { 
 public static void main(String[] args) {
     
         ArrayList<Student> st = new ArrayList<Student>();
         st.add(new Student("김길동",20));
         st.add(new Student("박길동",32));
         st.add(new Student("홍길동",16));
         
         // Comparable 오름차순 정렬 (이름)
         Collections.sort(st);    
         System.out.println("Comparable(Asc) : "+st);
 
         // Comparator 내림차순 정렬 (이름)
         Collections.sort(st,new StudentSort());    
         System.out.println("Comparator(Desc) : "+st);
         
         // 익명 클래스 내림차순 정렬 (나이)
         Collections.sort(st,new StudentSort() {
             @Override
             public int compare(Student s1, Student s2) {
                 return s2.age - s1.age;
             }
         });    
         System.out.println("AnonymousClass(Desc) : "+st);
     }
 }
 
// Comparable 구현
class Student implements Comparable<Student>{
    String name;
    int age;
    
    public Student(String name, int age) {
        this.name=name;
        this.age=age;
    }
    
    @Override
    public int compareTo(Student s) {
        return name.compareTo(s.name);
 
        // 정수형 오름차순 방법 
//        return Integer.compare(age,s.age);
//        return age-s.age;
        
//        if(age>s.age) return 1;
//        else if(age<s.age) return -1;
//        else return 0;
    }
    
    @Override
    public String toString() {
        return "["+name+", "+age+"]";
    }    
}
 
// Comparator 구현
class StudentSort implements Comparator<Student>{
    @Override
    public int compare(Student s1, Student s2) {
        return s2.name.compareTo(s1.name);
 
        // 정수형 내림차순 방법
//        return Integer.compare(s2.age, s1.age);
//        return s2.age-s1.age;
        
//        if(s1.age<s2.age) return 1;
//        else if(s1.age>s2.age) return -1;
//        else return 0;
    }
}
결과
Comparable(Asc) : [[김길동, 20], [박길동, 32], [홍길동, 16]]
Comparator(Desc) : [[홍길동, 16], [박길동, 32], [김길동, 20]]
AnonymousClass(Desc) : [[박길동, 32], [김길동, 20], [홍길동, 16]]

 

 

 

[References]

namocom.tistory.com/871

gmlwjd9405.github.io/2018/09/06/java-comparable-and-comparator.html