웹사이트 검색

Java 예제의 Comparable 및 Comparator


Java의 Comparable 및 Comparator는 개체 컬렉션을 정렬하는 데 매우 유용합니다. Java는 기본 유형 배열 또는 래퍼 클래스 배열 또는 목록을 정렬하는 몇 가지 내장 메서드를 제공합니다. 여기서는 먼저 원시 유형 및 래퍼 클래스의 배열/목록을 정렬하는 방법을 배운 다음 java.lang.Comparable 및 java.util.Comparator 인터페이스를 사용하여 사용자 정의 클래스의 배열/목록을 정렬하는 방법을 배웁니다. 간단한 프로그램으로 기본 유형 또는 객체 배열 및 목록을 정렬하는 방법을 살펴보겠습니다.

package com.journaldev.sort;

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

public class JavaObjectSorting {

    /**
     * This class shows how to sort primitive arrays, 
     * Wrapper classes Object Arrays
     * @param args
     */
    public static void main(String[] args) {
        //sort primitives array like int array
        int[] intArr = {5,9,1,10};
        Arrays.sort(intArr);
        System.out.println(Arrays.toString(intArr));
        
        //sorting String array
        String[] strArr = {"A", "C", "B", "Z", "E"};
        Arrays.sort(strArr);
        System.out.println(Arrays.toString(strArr));
        
        //sorting list of objects of Wrapper classes
        List<String> strList = new ArrayList<String>();
        strList.add("A");
        strList.add("C");
        strList.add("B");
        strList.add("Z");
        strList.add("E");
        Collections.sort(strList);
        for(String str: strList) System.out.print(" "+str);
    }
}

위 프로그램의 출력은 다음과 같습니다.

[1, 5, 9, 10]
[A, B, C, E, Z]
 A B C E Z

이제 객체 배열을 정렬해 보겠습니다.

package com.journaldev.sort;

public class Employee {

    private int id;
    private String name;
    private int age;
    private long salary;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public long getSalary() {
        return salary;
    }

    public Employee(int id, String name, int age, int salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
    //this is overridden to print the user-friendly information about the Employee
    public String toString() {
        return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
                this.salary + "]";
    }

}

다음은 Employee 개체의 배열을 정렬하는 데 사용한 코드입니다.

//sorting object array
Employee[] empArr = new Employee[4];
empArr[0] = new Employee(10, "Mikey", 25, 10000);
empArr[1] = new Employee(20, "Arun", 29, 20000);
empArr[2] = new Employee(5, "Lisa", 35, 5000);
empArr[3] = new Employee(1, "Pankaj", 32, 50000);

//sorting employees array using Comparable interface implementation
Arrays.sort(empArr);
System.out.println("Default Sorting of Employees list:\n"+Arrays.toString(empArr));

이것을 실행하려고 하면 다음과 같은 런타임 예외가 발생합니다.

Exception in thread "main" java.lang.ClassCastException: com.journaldev.sort.Employee cannot be cast to java.lang.Comparable
	at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:290)
	at java.util.ComparableTimSort.sort(ComparableTimSort.java:157)
	at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
	at java.util.Arrays.sort(Arrays.java:472)
	at com.journaldev.sort.JavaSorting.main(JavaSorting.java:41)

비교 대상 및 비교 대상

package com.journaldev.sort;

import java.util.Comparator;

public class Employee implements Comparable<Employee> {

    private int id;
    private String name;
    private int age;
    private long salary;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public long getSalary() {
        return salary;
    }

    public Employee(int id, String name, int age, int salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
    public int compareTo(Employee emp) {
        //let's sort the employee based on an id in ascending order
        //returns a negative integer, zero, or a positive integer as this employee id
        //is less than, equal to, or greater than the specified object.
        return (this.id - emp.id);
    }

    @Override
    //this is required to print the user-friendly information about the Employee
    public String toString() {
        return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
                this.salary + "]";
    }

}

이제 직원의 배열 정렬에 대해 위의 스니펫을 실행하고 인쇄하면 다음과 같은 결과가 나타납니다.

Default Sorting of Employees list:
[[id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000]]

직원 배열이 ID별로 오름차순으로 정렬되어 있음을 알 수 있습니다. 그러나 대부분의 실제 시나리오에서는 다른 매개변수를 기반으로 정렬을 원합니다. 예를 들어 CEO는 급여를 기준으로 직원을 정렬하고 HR은 연령을 기준으로 직원을 정렬하고 싶습니다. Comparable.compareTo(Object o) 메서드 구현이 기본 정렬을 제공할 수 있고 동적으로 변경할 수 없기 때문에 Java Comparator 인터페이스를 사용해야 하는 상황입니다. Comparator를 사용하면 서로 다른 정렬 방법으로 여러 메서드를 정의한 다음 요구 사항에 따라 정렬 방법을 선택할 수 있습니다.

자바 비교기

Comparator 인터페이스 compare(Object o1, Object o2) 메서드는 두 개의 Object 인수를 받는 방식으로 구현해야 하며, 첫 번째 인수가 두 번째 인수보다 작으면 음의 int를 반환하도록 구현해야 합니다. 1이고 같으면 0을 반환하고 첫 번째 인수가 두 번째 인수보다 크면 양의 int를 반환합니다. Comparable 및 Comparator 인터페이스는 컴파일 타임 유형 검사를 위해 Generics를 사용합니다. Java Generics에 대해 자세히 알아보세요. Employee 클래스에서 다른 Comparator 구현을 만드는 방법은 다음과 같습니다.

/**
     * Comparator to sort employees list or array in order of Salary
     */
    public static Comparator<Employee> SalaryComparator = new Comparator<Employee>() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return (int) (e1.getSalary() - e2.getSalary());
        }
    };

    /**
     * Comparator to sort employees list or array in order of Age
     */
    public static Comparator<Employee> AgeComparator = new Comparator<Employee>() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getAge() - e2.getAge();
        }
    };

    /**
     * Comparator to sort employees list or array in order of Name
     */
    public static Comparator<Employee> NameComparator = new Comparator<Employee>() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getName().compareTo(e2.getName());
        }
    };

위의 모든 Comparator 인터페이스 구현은 익명 클래스입니다. 이러한 비교기를 사용하여 배열 및 컬렉션 클래스의 정렬 기능에 인수를 전달할 수 있습니다.

//sort employees array using Comparator by Salary
Arrays.sort(empArr, Employee.SalaryComparator);
System.out.println("Employees list sorted by Salary:\n"+Arrays.toString(empArr));

//sort employees array using Comparator by Age
Arrays.sort(empArr, Employee.AgeComparator);
System.out.println("Employees list sorted by Age:\n"+Arrays.toString(empArr));

//sort employees array using Comparator by Name
Arrays.sort(empArr, Employee.NameComparator);
System.out.println("Employees list sorted by Name:\n"+Arrays.toString(empArr));

다음은 위 코드 스니펫의 출력입니다.

Employees list sorted by Salary:
[[id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000]]
Employees list sorted by Age:
[[id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000]]
Employees list sorted by Name:
[[id=20, name=Arun, age=29, salary=20000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=1, name=Pankaj, age=32, salary=50000]]

이제 우리는 Java 객체 배열 또는 목록을 정렬하려면 기본 정렬을 제공하기 위해 Java Comparable 인터페이스를 구현해야 하고 다양한 정렬 방법을 제공하기 위해 Java Comparator 인터페이스를 구현해야 한다는 것을 알고 있습니다. Comparator 인터페이스를 구현하는 별도의 클래스를 생성하여 사용할 수도 있습니다. 다음은 Java에서 Comparable 및 Comparator를 설명하는 마지막 클래스입니다.

package com.journaldev.sort;

import java.util.Comparator;

public class Employee implements Comparable<Employee> {

    private int id;
    private String name;
    private int age;
    private long salary;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public long getSalary() {
        return salary;
    }

    public Employee(int id, String name, int age, int salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
    public int compareTo(Employee emp) {
        //let's sort the employee based on an id in ascending order
        //returns a negative integer, zero, or a positive integer as this employee id
        //is less than, equal to, or greater than the specified object.
        return (this.id - emp.id);
    }

    @Override
    //this is required to print the user-friendly information about the Employee
    public String toString() {
        return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
                this.salary + "]";
    }

    /**
     * Comparator to sort employees list or array in order of Salary
     */
    public static Comparator<Employee> SalaryComparator = new Comparator<Employee>() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return (int) (e1.getSalary() - e2.getSalary());
        }
    };

    /**
     * Comparator to sort employees list or array in order of Age
     */
    public static Comparator<Employee> AgeComparator = new Comparator<Employee>() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getAge() - e2.getAge();
        }
    };

    /**
     * Comparator to sort employees list or array in order of Name
     */
    public static Comparator<Employee> NameComparator = new Comparator<Employee>() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getName().compareTo(e2.getName());
        }
    };
}

다음은 두 직원 개체를 ID에서 먼저 비교하고 동일한 경우 이름에서 비교하는 Comparator 인터페이스의 별도 클래스 구현입니다.

package com.journaldev.sort;

import java.util.Comparator;

public class EmployeeComparatorByIdAndName implements Comparator<Employee> {

    @Override
    public int compare(Employee o1, Employee o2) {
        int flag = o1.getId() - o2.getId();
        if(flag==0) flag = o1.getName().compareTo(o2.getName());
        return flag;
    }

}

다음은 Comparable 및 Comparator를 사용하여 Java에서 객체를 정렬하는 다양한 방법을 사용하는 테스트 클래스입니다.

package com.journaldev.sort;

import java.util.Arrays;

public class JavaObjectSorting {

    /**
     * This class shows how to sort custom objects array/list
     * implementing Comparable and Comparator interfaces
     * @param args
     */
    public static void main(String[] args) {

        //sorting custom object array
        Employee[] empArr = new Employee[4];
        empArr[0] = new Employee(10, "Mikey", 25, 10000);
        empArr[1] = new Employee(20, "Arun", 29, 20000);
        empArr[2] = new Employee(5, "Lisa", 35, 5000);
        empArr[3] = new Employee(1, "Pankaj", 32, 50000);
        
        //sorting employees array using Comparable interface implementation
        Arrays.sort(empArr);
        System.out.println("Default Sorting of Employees list:\n"+Arrays.toString(empArr));
        
        //sort employees array using Comparator by Salary
        Arrays.sort(empArr, Employee.SalaryComparator);
        System.out.println("Employees list sorted by Salary:\n"+Arrays.toString(empArr));
        
        //sort employees array using Comparator by Age
        Arrays.sort(empArr, Employee.AgeComparator);
        System.out.println("Employees list sorted by Age:\n"+Arrays.toString(empArr));
        
        //sort employees array using Comparator by Name
        Arrays.sort(empArr, Employee.NameComparator);
        System.out.println("Employees list sorted by Name:\n"+Arrays.toString(empArr));
        
        //Employees list sorted by ID and then name using Comparator class
        empArr[0] = new Employee(1, "Mikey", 25, 10000);
        Arrays.sort(empArr, new EmployeeComparatorByIdAndName());
        System.out.println("Employees list sorted by ID and Name:\n"+Arrays.toString(empArr));
    }

}

다음은 위 프로그램의 출력입니다.

Default Sorting of Employees list:
[[id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000]]
Employees list sorted by Salary:
[[id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000]]
Employees list sorted by Age:
[[id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000]]
Employees list sorted by Name:
[[id=20, name=Arun, age=29, salary=20000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=1, name=Pankaj, age=32, salary=50000]]
Employees list sorted by ID and Name:
[[id=1, name=Mikey, age=25, salary=10000], [id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000]]

java.lang.Comparable 및 java.util.Comparator는 Java에서 객체 정렬을 제공하는 데 사용할 수 있는 강력한 인터페이스입니다.

비교 가능 대 비교기

  1. Comparable 인터페이스는 단일 정렬 방법을 제공하는 데 사용할 수 있는 반면 Comparator 인터페이스는 다양한 정렬 방법을 제공하는 데 사용됩니다.
  2. Comparable을 사용하려면 Class에서 구현해야 하지만 Comparator를 사용하려면 클래스를 변경할 필요가 없습니다.
  3. Comparable 인터페이스는 java.lang 패키지에 있고 Comparator 인터페이스는 java.util 패키지에 있습니다.
  4. 비교 가능, Arrays.sort() 또는 Collection.sort() 메서드를 사용하기 위해 클라이언트 측에서 코드를 변경할 필요가 없습니다.compareTo() 클래스의 메소드. Comparator의 경우 클라이언트는 compare() 메서드에서 사용할 Comparator 클래스를 제공해야 합니다.

Comparator 인수를 취하는 Collections.sort() 메서드가 전략 패턴을 따른다는 사실을 알고 계십니까?

GitHub 리포지토리에서 전체 코드와 더 많은 핵심 Java 예제를 체크아웃할 수 있습니다.