Comparable And Comparator 란?

두 개 모두 interface이며, 객체를 정렬시키는데 이용됩니다. 정렬을 이용하기 위해선 함수를 구현해야 합니다. 


Comparable과 Comparator 기본 사용

1. Comparable

public interface Comparable<T> {  // 제네릭이 사용됩니다.
    public int compareTo(T o);
}
  • compareTo() 구현합니다. 
  • 반환형이 int입니다. 양수, 0, 음수로 구분되어 정렬을 결정합니다.
  • 0과 음수일 때는 순서를 바꾸지 않고 양수일 때 변경합니다. 
  • 비교하는 대상을 설정하고, 현재 객체와 다른 객체를 비교합니다.
class Node implements Comparable<Node>{
    int score;

    public Node(int score) {
        this.score = score;
    }

    @Override
    public int compareTo(Node o) {
        return this.score-o.score;
    }
}

public class Main {
    public static void main(String[] args) throws IOException {

        List<Node> nodes = new ArrayList<>();
        nodes.add(new Node(1));
        nodes.add(new Node(4));
        nodes.add(new Node(2));
        nodes.add(new Node(3));

        for(Node now: nodes){
            System.out.println(now.score); // 1 4 2 3 그대로 출력
        }

        Collections.sort(nodes); // 오른차순 정렬됩니다.

        System.out.println("--------");
        
        for(Node now: nodes){
            System.out.println(now.score); // 1 2 3 4 출력 
        }
    }
}

위의 코드에서 현재 객체와 다른 객체의 score 값을 비교합니다. 

ex) 1=현재 객체 4= 다른 객체가 들어왔다면, 1-4=-3 음수이므로 위치를 변경하지 않습니다.

ex) 4=현재 객체 2= 다른 객체가 들어왔다면, 4-2=2 양수이므로 위치를 변경합니다. 

 

2. Comparator

public interface Comparator<T> {
    int compare(T o1, T o2);
}
  • compare()을 구현합니다.
  • 반환형이 int입니다. 양수, 0, 음수로 구분되어 정렬을 결정합니다.
  • 0과 음수일 때는 순서를 바꾸지 않고 양수일 때 변경합니다.
  • Comparable과는 다르게 두 객체가 들어오며, 두 객체를 비교합니다.
class Node{
    int score;

    public Node(int score) {
        this.score = score;
    }
}

public class Main {
    public static void main(String[] args) throws IOException {

        List<Node> nodes = new ArrayList<>();
        nodes.add(new Node(1));
        nodes.add(new Node(4));
        nodes.add(new Node(2));
        nodes.add(new Node(3));

        for(Node now: nodes){
            System.out.println(now.score);
        }

        Collections.sort(nodes, new Comparator<Node>() {
            @Override
            public int compare(Node o1, Node o2) {
                return -(o1.score-o2.score); // 기존 값의 -를 붙여 음수이므로 내림차순 정렬됩니다.
            }
        });

        System.out.println("--------");
        for(Node now: nodes){
            System.out.println(now.score);
        }
    }
}

위의 코드에서 두 객체가 들어오며, 비교하여 정렬합니다.

 

ex) 1= a객체 4= b객체가 들어왔다면, 1-4=-(-3) 양수이므로 위치를 변경합니다.

ex) 4= a객체 2= b객체가 들어왔다면, 4-2=-(2) 음수이므로 위치를 변경하지 않습니다.


Comparable와 Comparator 응용

 

1. Comparable 여러 인자 비교

Node 클래스는 score와 size가 있습니다. Comparable을 통해서 내림차순을 정렬하며, score가 우선순위 size는 후위입니다.

class Node implements Comparable<Node>{
    int score;
    int size;
    public Node(int score, int size) {
        this.score = score;
        this.size=size;
    }

    @Override
    public int compareTo(Node o) { // score가 작은 것부터 하며 같다면 size까지 비교합니다. 
        if(this.score>o.score){
            return 1;
        }
        else if(this.score==o.score){
            return this.size-o.size;
        }
        else{
            return -1;
        }
    }
}

public class Main {
    public static void main(String[] args) throws IOException {

        List<Node> nodes = new ArrayList<>();
        nodes.add(new Node(1,2));
        nodes.add(new Node(4,4));
        nodes.add(new Node(2,1));
        nodes.add(new Node(3,6));
        nodes.add(new Node(1,1));
        for(Node now: nodes){
		System.out.println(now.score+" "+now.size); 
// 출력
// 1 2
// 4 4
// 2 1
// 3 6
// 1 1
        }

        Collections.sort(nodes);

        System.out.println("--------");
        for(Node now: nodes){
            System.out.println(now.score +" "+ now.size);
        }
// 출력
// 1 1
// 1 2
// 2 1
// 3 6
// 4 4
    }
}

2. Comparator 여러 인자 비교

class Node{
    int score;
    int size;
    public Node(int score, int size) {
        this.score = score;
        this.size=size;
    }
}

public class Main {
    public static void main(String[] args) throws IOException {

        List<Node> nodes = new ArrayList<>();
        nodes.add(new Node(1,2));
        nodes.add(new Node(4,4));
        nodes.add(new Node(2,1));
        nodes.add(new Node(3,6));
        nodes.add(new Node(1,1));
        for(Node now: nodes){
            System.out.println(now.score+" "+now.size);
        }

        Collections.sort(nodes, new Comparator<Node>() { // Comparator 구현 
            @Override
            public int compare(Node o1, Node o2) {
                if(o1.score>o2.score){
                    return 1;
                }
                else if(o1.score==o2.score){
                    return o1.size-o2.size;
                }
                else{
                    return -1;
                }
            }
        });

        System.out.println("--------");
        for(Node now: nodes){
            System.out.println(now.score +" "+ now.size);
        }
    }
}

3. Comparator 람다식 사용

interface의 메소드가 하나만 있다면, 람다를 이용해서 코드를 직관성 있게 작성이 가능합니다.

class Node{
    int score;
    int size;
    public Node(int score, int size) {
        this.score = score;
        this.size=size;
    }
}

public class Main {
    public static void main(String[] args) throws IOException {

        List<Node> nodes = new ArrayList<>();
        nodes.add(new Node(1,2));
        nodes.add(new Node(4,4));
        nodes.add(new Node(2,1));
        nodes.add(new Node(3,6));
        nodes.add(new Node(1,1));
        for(Node now: nodes){
            System.out.println(now.score+" "+now.size);
        }

        Collections.sort(nodes, (a,b) -> { // 람다 사용
            if(a.score>b.score){
                return 1;
            }
            else if(a.score==b.score){
                return a.size-b.size;
            }
            else{
                return -1;
            }
        });

        System.out.println("--------");
        for(Node now: nodes){
            System.out.println(now.score +" "+ now.size);
        }
    }
}

 

 

지금까지 Comparable과 Comparator를 알아봤습니다. 잘못된 부분에 대한 지적 해주신다면 감사합니다. 

'JAVA' 카테고리의 다른 글

JAVA Enum  (0) 2022.02.24
JAVA Stream  (0) 2022.02.23
JAVA Optional<T>  (0) 2022.02.23
JAVA 람다(lambda)  (0) 2022.02.21
Java 제네릭(Generic)  (0) 2022.02.20