Menu
Coddy logo textTech

Comparator 인터페이스

Coddy Java 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 87개 중 45번째.

Comparable이 클래스의 자연스러운 정렬 순서를 정의하는 반면, 때로는 객체를 다른 방식으로 정렬해야 할 때가 있습니다. Comparator 인터페이스를 사용하면 원래 클래스를 수정하지 않고도 별도의 비교 로직을 만들 수 있습니다.

Comparator는 동일한 타입의 두 객체를 비교하는 외부 객체입니다. 이는 여러 정렬 옵션을 원하거나 클래스 자체를 수정할 수 없을 때 유용합니다:

import java.util.Comparator;

class NameComparator implements Comparator<Person> {
    @Override
    public int compare(Person p1, Person p2) {
        return p1.getName().compareTo(p2.getName());
    }
}

class AgeComparator implements Comparator<Person> {
    @Override
    public int compare(Person p1, Person p2) {
        return p1.getAge() - p2.getAge();
    }
}

그런 다음 비교자를 정렬 메서드에 전달할 수 있습니다:

List<Person> people = new ArrayList<>();
people.add(new Person("Charlie", 30));
people.add(new Person("Alice", 25));

Collections.sort(people, new NameComparator());  // 이름순으로 정렬
Collections.sort(people, new AgeComparator());   // 나이순으로 정렬

간결한 코드를 위해, Comparator는 함수형 인터페이스이므로 람다 표현식을 사용할 수 있습니다:

Collections.sort(people, (p1, p2) -> p1.getName().compareTo(p2.getName()));

핵심적인 차이점: Comparable은 비교 대상이 되는 클래스에 의해 구현되며 하나의 자연스러운 순서(natural order)를 정의하는 반면, Comparator는 무제한의 사용자 정의 정렬을 정의할 수 있는 별도의 클래스입니다.

challenge icon

챌린지

쉬움

Comparator 인터페이스의 강력함을 보여주는 직원 정렬 시스템을 구축해 보겠습니다. Employee 클래스 자체를 수정하지 않고도 급여별, 이름별 등 다양한 방식으로 직원을 정렬하기 위해 여러 개의 comparator를 만들 것입니다.

코드는 다음 네 개의 파일로 구성됩니다:

  • Employee.java: 세 개의 private 필드 name (String), department (String), salary (double)를 가진 직원을 나타내는 클래스를 만듭니다. 모든 필드를 초기화하는 생성자와 각 필드에 대한 getter 메서드를 포함하세요. toString()을 오버라이드하여 [name] ([department]) - $[salary] 형식을 반환하도록 합니다.
  • SalaryComparator.java: 직원을 급여 기준 내림차순(높은 급여가 먼저 오도록)으로 정렬하는 comparator를 만듭니다. Comparator<Employee> 인터페이스와 그 compare() 메서드를 구현하세요. 급여 값의 안전한 비교를 위해 Double.compare()를 사용하세요.
  • NameComparator.java: 직원을 이름 기준 알파벳 오름차순(A부터 Z까지)으로 정렬하는 또 다른 comparator를 만듭니다. Comparator<Employee>를 구현하고 비교를 위해 String의 compareTo() 메서드를 사용하세요.
  • Main.java: 직원 리스트를 생성하고 작성한 comparator를 사용하여 정렬함으로써 모든 것을 하나로 합칩니다. 세 명의 직원에 대한 입력을 받게 되며, 각 줄은 name,department,salary 형식입니다.

    직원들의 ArrayList를 생성한 다음, 두 가지 정렬 방식을 모두 보여주세요:

    1. 먼저, SalaryComparator를 사용하여 급여순으로 정렬하고 각 직원을 출력합니다.
    2. 빈 줄을 하나 출력합니다.
    3. 그런 다음 NameComparator를 사용하여 이름순으로 정렬하고 각 직원을 출력합니다.

각각 name,department,salary 형식의 직원 데이터를 포함하는 세 줄의 입력을 받게 됩니다.

예를 들어, 입력 줄은 다음과 같을 수 있습니다: Alice,Engineering,75000.0

comparator 파일에서는 java.util.Comparator를 임포트하고, Main 파일에서는 java.util.ArrayList, java.util.Collections, java.util.Scanner를 임포트하는 것을 잊지 마세요. comparator를 사용하면 외부에서 여러 정렬 전략을 정의할 수 있다는 점에 주목하세요. Employee 클래스는 자신이 어떻게 정렬될지에 대해 전혀 알 필요가 없습니다!

치트 시트

Comparator 인터페이스를 사용하면 원래 클래스를 수정하지 않고도 객체 정렬을 위한 외부 비교 로직을 만들 수 있습니다. 이는 여러 가지 정렬 옵션이 필요할 때 유용합니다.

Comparatorcompare() 메서드를 구현하여 동일한 타입의 두 객체를 비교합니다:

import java.util.Comparator;

class NameComparator implements Comparator<Person> {
    @Override
    public int compare(Person p1, Person p2) {
        return p1.getName().compareTo(p2.getName());
    }
}

정렬 메서드에 comparator를 전달합니다:

Collections.sort(people, new NameComparator());

Comparator는 함수형 인터페이스이므로 람다 표현식을 사용하여 간결한 코드를 작성할 수 있습니다:

Collections.sort(people, (p1, p2) -> p1.getName().compareTo(p2.getName()));

숫자 값을 비교할 때는 안전한 비교를 위해 Double.compare()와 같은 래퍼 클래스 메서드를 사용하세요:

class AgeComparator implements Comparator<Person> {
    @Override
    public int compare(Person p1, Person p2) {
        return p1.getAge() - p2.getAge();
    }
}

주요 차이점: Comparable은 클래스 자체 내에서 하나의 자연스러운 순서를 정의하는 반면, Comparator는 외부에서 무제한으로 사용자 정의 순서를 정의할 수 있는 별도의 클래스입니다.

직접 해보기

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 입력으로부터 세 명의 직원을 읽어옵니다
        // 각 줄의 형식: name,department,salary
        String line1 = scanner.nextLine();
        String line2 = scanner.nextLine();
        String line3 = scanner.nextLine();
        
        // TODO: 각 줄을 파싱하고 Employee 객체를 생성하세요
        // 힌트: 값을 분리하려면 split(",")를 사용하세요
        
        // TODO: 직원들의 ArrayList를 생성하고 세 명을 모두 추가하세요
        
        // TODO: SalaryComparator를 사용하여 급여순으로 정렬하고 각 직원을 출력하세요
        // 힌트: Collections.sort(list, comparator)를 사용하세요
        
        // TODO: 빈 줄을 출력하세요
        
        // TODO: NameComparator를 사용하여 이름순으로 정렬하고 각 직원을 출력하세요
    }
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨