Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

자바(Java) Comparable과 Comparator의 차이점 완벽 정리

자바에서 ComparableComparator는 모두 컬렉션의 요소를 정렬하는 데 사용되는 인터페이스입니다. 두 인터페이스는 목적이 같지만, 소속 패키지와 객체 비교 방식에서 뚜렷한 차이가 있습니다.

Comparatorjava.util 패키지에 속하며, 전달받은 두 개의 객체를 서로 비교합니다. 반면 Comparablejava.lang 패키지에 속하며, 자기 자신(this)과 매개변수로 전달된 객체 하나를 비교합니다.

Comparable과 Comparator 핵심 차이점 비교

번호구분ComparableComparator
1메서드compareTo(Object a) 메서드를 제공합니다.compare(Object o1, Object o2) 메서드를 제공합니다.
2정렬 호출Collections.sort(List) 메서드로 Comparable 타입 객체의 컬렉션을 정렬합니다.Collections.sort(List, Comparator) 메서드로 Comparator 타입 객체의 컬렉션을 정렬합니다.
3정렬 기준단일 정렬 기준만 제공합니다.여러 개의 정렬 기준을 제공할 수 있습니다.
4소속 패키지java.lang 패키지에 속합니다.java.util 패키지에 속합니다.

Comparable 예제

아래 예제는 Laptop 클래스가 Comparable<Laptop> 인터페이스를 구현하여, RAM 용량을 기준으로 노트북 목록을 오름차순으로 정렬하는 코드입니다. compareTo() 메서드 내부에서 현재 객체(this.ram)와 비교 대상 객체(o.getRam())를 직접 비교한다는 점에 주목하세요.

public class ComparableExample {
    public static void main(String[] args) {
        List<Laptop> laptopList = new ArrayList<>();
        laptopList.add(new Laptop("HCL", 16, 800));
        laptopList.add(new Laptop("Apple", 8, 100));
        laptopList.add(new Laptop("Dell", 4, 600));
        Collections.sort(laptopList);
        for (Laptop lap : laptopList) {
            System.out.println(lap.getRam());
        }
    }
}
public class Laptop implements Comparable<Laptop> {
    String name;
    int ram;
    int price;
    public Laptop(String name, int ram, int price) {
        super();
        this.name = name;
        this.ram = ram;
        this.price = price;
    }
    public String getName() {
        return name;
    }
    public int getRam() {
        return ram;
    }
    public void setRam(int ram) {
        this.ram = ram;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getPrice() {
        return price;
    }
    public void setPrice(int price) {
        this.price = price;
    }
    @Override
    public int compareTo(Laptop o) {
        if (this.ram > o.getRam())
            return 1;
        else {
            return -1;
        }
    }
}

실행 결과

4
8
16

Comparator 예제

다음 예제는 Comparator 인터페이스를 활용한 정렬 방법입니다. compare() 메서드는 비교 대상인 두 객체(o1, o2)를 매개변수로 받으며, 람다 표현식을 사용하면 이름 기준 정렬처럼 새로운 정렬 규칙을 기존 코드 수정 없이 간단히 추가할 수 있습니다.

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Laptop implements Comparator {
    String name;
    int ram;
    int price;
    public Laptop(String name, int ram, int price) {
        super();
        this.name = name;
        this.ram = ram;
        this.price = price;
    }
    public String getName() {
        return name;
    }
    public int getRam() {
        return ram;
    }
    public void setRam(int ram) {
        this.ram = ram;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getPrice() {
        return price;
    }
    public void setPrice(int price) {
        this.price = price;
    }
    @Override
    public int compare(Laptop o1, Laptop o2) {
        if (o1.getRam() < o2.getRam()) {
            return -1;
        } else if (o1.getRam() > o2.getRam()) {
            return 1;
        } else {
            return 0;
        }
    }
    public static void main(String[] args) {
        List laptopList = new ArrayList<>();
        laptopList.add(new Laptop("HCL", 16, 800));
        laptopList.add(new Laptop("Apple", 8, 100));
        laptopList.add(new Laptop("Dell", 4, 600));
        Comparator com = (Laptop o1, Laptop o2) -> o1.getName().compareTo(o2.getName());
        Collections.sort(laptopList, com);
        for (Laptop lap : laptopList) {
            System.out.println(lap.getName());
        }
    }
}

실행 결과

Apple
Dell
HCL

어떤 것을 선택해야 할까?

두 인터페이스 중 무엇을 사용할지는 개발 상황에 따라 달라집니다.

  • Comparable: 클래스의 기본 정렬 순서(natural ordering)를 하나만 정의하면 될 때 적합합니다. 나이순, 이름순처럼 고정된 기준으로 정렬하는 경우에 사용합니다.
  • Comparator: 여러 가지 정렬 기준이 필요하거나, 소스 코드를 수정할 수 없는 외부 라이브러리 클래스를 정렬해야 할 때 유용합니다. 람다 표현식과 함께 사용하면 정렬 로직을 유연하게 교체할 수 있습니다.