본문 바로가기
프로그래밍/Java

Java Comparable, Comparator

by so5663 2023. 1. 11.

 

 

public class Main {
 
    public static void main(String[] args) {
        int a = 3, b = 5;
        System.out.println(a > b);
        System.out.println(a < b);
        
        String str1 = "abc", str2 = "abc";
        System.out.println(str1.equals(str2));
    }
}

이런식으로 primitive type은 자바 자체에서 제공되기에 별다른 처리 없이 비교가 가능하다. 즉, 기본 자료형이기 때문에 부등호로 쉽게 비교가 가능하다.

그러나 주로 알고리즘 문제를 풀때 map이나, 객체를 정렬할때는 어떤 것 기준으로 비교할지 컴파일러는 알 수 없다.

그 때 사용하는게 Comparable과 Comparator이다.

 

Comparable과 Comparator는 둘다 인터페이스(interface)이다.

Comparable 인터페이스를 쓰려면 compareTo 메소드를 구현해야하고,

Comparator 인터페이스를 쓰려면 compre 메소드를 구현해야 한다는 점이다.

 

Comparable "자기 자신과 매개변수 객체를 비교"하는 것이고,  주로 기본 정렬기준을 구현하는데 사용.

Comparator는 "두 매개변수 객체를 비교"한다는 것이다. 주로 기본 정렬기준 외에 다른 기준으로 정렬하고자할 때 사용. 

 

리턴값에 따라 정렬 방법이 달리진다.

  • 현재 객체 < 파라미터로 넘어온 객체 : 음수 리턴
  • 현재 객체 == 파라미터로 넘어온 객체 : 0 리턴 
  • 현재 객체 > 파라미터로 넘어온 객체 : 양수 리턴
  • 음수 또는 0이면 객체의 자리가 그대로 유지됨. 
  • 양수일 경우 두 객체의 자리가 바뀐다. 

 

Comparable

class Book implements Comparable<Book> { // Comparable 구현
    private String title;
    private String author;
    private String company;
    private int year;

    public Book(String a, String b, String c, int d) {
        this.title = a;
        this.author = b;
        this.company = c;
        this.year = d;
    }
    
    public String getTitle() {
    	return title;
    }
    
    public int getYear() {
    	return year;
    }
}

 

 

// ex1) 출판년도(year) 오름차순 
public int compareTo(Book obj) {
    if (this.year == obj.year) { 
        return 0; 
        // 현재 객체 == 파라미터로 넘어온 객체 ==> 0 리턴 
    } else if(this.year < obj.year) { 
        return -1; 
    	// 현재 객체 < 파라미터로 넘어온 객체 ==> 음수 리턴  ==> 자리 바뀌지 X ==> 오름차순 
    } else { 
        return 1;
    	// 현재 객체 > 파라미터로 넘어온 객체 ==> 양수 리턴 ==> 자리 바뀌지 O ==> 오름차순 
    }
}

 

 

// ex2) 책 제목 사전 순 
public int compareTo(Book o) {
    int res = this.getTitle().compareTo(o.getTitle());
    return res;
}

 

 

// ex3) 책 제목 사전순으로. 책 제목이 같을 경우, 출간년도 오름차순으로
public int compareTo(Book o) {
    int res = this.getTitle().compareTo(o.getTitle());
    if(res==0) res = this.getYear() - o.getYear();
    // 현재 객체 출판년도 > 파라미터로 넘어온 객체 출판년도 ==> 양수 리턴 ==> 자리 바뀌지 O ==> 오름차순 
    return res;
}

 

this.getTitle().compareTo(o.getTitle()); --> this.getTitle() - o.getTitle(); //변경가능

 

Comparator

class Book implements Comparator<Book> { // Comparator 구현
    private String title;
    private String author;
    private String company;
    private int year;

    public Book(String a, String b, String c, int d) {
        this.title = a;
        this.author = b;
        this.company = c;
        this.year = d;
    }
    
    public String getTitle() {
    	return title;
    }
    
    public int getYear() {
    	return year;
    }
}

 

 


public int compare(Book o1, Book o2) {
    if(o1.getYear()>o2.getYear()) {
        return -1;
    }else if(o1.getYear()<o2.getYear()) {
        return 1;
    }else {
    	if(o1.getYear() == o2.getYear()) {
    		return o1.getTitle() - o2.getTitle(); //오름차순
        }else return 0;
    }
}

이런식으로 사용합니다.

 

예외로

Collections.sort() VS Arrays.sort() 
일반적으로 Collections.sort는 List를 정렬할 때, Arrays.sort는 배열을 정렬할때 쓰인다.
또한 정렬의 방식에도 차이가 있는데
Collections.sort는 TimeSort (삽입정렬과 합병정렬을 결합한 정렬)이라 평균, 최악 둘다 nlogn인 반면Arrays.sort는 DualPivotQuicksort 정렬이라 평균은 nlogn인데 최악은 n^2이므로
속도에도 차이가 있음을 알 수 있다.