개발자가 되고 싶은 개발자

[Java] Comparator 본문

Dev/Java & Spring

[Java] Comparator

Fullth 2021. 12. 24. 10:29

Java에서의 정렬

자바에서 데이터를 정렬해야 할 때,

기본적인 정렬은 java.util 패키지에 정의되어 있는 Arrays와 Collections의 sort메소드를 사용합니다.

int[] randomNum = {3, 4, 6, 3, 2};
Arrays.sort(randomNum);

String[] fruits = {"apple", "banana", "kiwi"};
Arrays.sort(fruits);

ArrayList<String> alphabetList = new ArrayList<>(Arrays.asList("C", "A", "B", "a"));
Collections.sort(alphabetList);

위의 예시대로 작성한다면, 기본 정렬인 오름차순으로 정렬하게 됩니다. 

기본적으로 제공되는 기능들로 오름차순, 내림차순 정렬과, 세 번째 예제와 같이 대소문자가 섞여 있는 경우의 정렬도 가능합니다.

 

단순히 오름차순, 내림차순으로 정렬하는 경우외에,

상황과 데이터 타입에 맞게 기준을 세워 정렬해야 하는 경우들이 있습니다.

그럴 경우, Comparator를 사용합니다.

Comparator Interface

Comparator 인터페이스는 java.util 패키지에 작성되어 있습니다. Java API문서를 통해서 알아보겠습니다.

 

method항목을 보시면, 많은 staic과 default method 그리고 abstract method 2개가 있습니다.

반드시 구현해야 하는 추상 메소드는 compare 메소드 한 개 입니다.

 

인터페이스에 작성되는 모든 메소드는 반드시 구현되어야 한다고 배웠기에 혼동이 있을 수 있지만,

Java8 부터 정의가 몇 가지 변경되었습니다.

 

인터페이스에서 메소드를 구현할 수 있으며, 해당 메소드를 오버라이딩 할 수 있습니다.

static 메소드를 작성하여, 오버라이딩은 불가능하지만 기능 제공 형식의 메소드를 작성할 수 있습니다.

 

equals 메소드는 아래 이미지와 같이 최상위 클래스인 Object 클래스의 메소드를 오버라이드 한 것이므로 구현하지 않아도 됩니다.

참고로 IDE와 API문서상의 주석을 비교해보도록 하겠습니다.

 

equals 메소드의 주석을 InteliJ IDE에서 열어본 모습입니다.

equals메소드는 자주 사용됨으로 문제가 없겠지만, API문서와는 조금 차이가 있으므로 API문서를 보실 것을 추천드립니다.

 

Compare 메소드 재정의

반드시 구현해야 하는 compare 메소드의 사용법만 알아보도록 하겠습니다.

/**
 * 생략... 
 * Returns a negative integer, zero, or a positive integer 
 * as the first argument is less than, equal to, or greater than the second.
 * 생략... 
 */
 
int compare(T o1, T o2);

compare메소드의 데이터 타입은 int형이고, 제네릭 타입의 매개변수 두 개를 전달받습니다.

음수, 0, 양수 중 하나를 반환합니다.

 

간단하게 학생의 나이를 비교하는 메소드를 재정의 해보겠습니다. 

class Student implements Comparator<Student> {

        private int grade;

        Student(int grade) {
            this.grade = grade;
        }

        public int getGrade() {
            return grade;
        }

        @Override
        public int compare(Student o1, Student o2) {
            if(o1.grade > o2.grade)
                return 1;
            else if(o1.grade == o2.grade)
                return 0;
            else
                return -1;
        }

        public static void main(String args[]) {
            Student adam = new Student(10);
            Student hawa = new Student(3);

            int chkCompare = adam.compare(adam, hawa);

            if(chkCompare > 0)
                System.out.println("adam > hawa");
            else if(chkCompare == 0)
                System.out.println("adam == hawa");
            else
                System.out.println("adam <> hawa");
        }
    }

인터페이스 이므로, 비교할 객체를 명세할 클래스에 상속받아 줍니다.

위와 같이 학생 객체를 나이순으로 비교할 수 있습니다.

 

단순 비교가 목적이 아니라, 비교할 기준을 세워 정렬하는 것이 목적이기 때문에,

Comparator를 사용하여 기준을 세우고, 반환하는 값을 이용하여 정렬에 활용할 수 있습니다.

학생 객체들을 나이별로 비교하여 내림차순 정렬하는 소스를 작성해보도록 하겠습니다.

public class testComparator {

    static class Student {

        private int age;

        Student(int age) {
            this.age = age;
        }

        public int getAge() {
            return age;
        }
    }

    public static void main(String args[]) {
        Student adam = new Student(10);
        Student hawa = new Student(3);

        List<Student> studentList = new ArrayList<>();
        studentList.add(hawa);
        studentList.add(adam);

        Collections.sort(studentList, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                if(o1.age < o2.age)
                    return 1;
                else if(o1.age == o2.age)
                    return 0;
                else
                    return -1;
            }
        });

        for(Student student : studentList)
            System.out.println(student.getAge());
    }
}

기준에 의하여 1, 0, -1 을 반환하고 있습니다. 이 수는 양수, 0, 음수를 반환하는 것과 같기 때문에,

이 둘의 차를 이용할 수 있습니다.

        Collections.sort(studentList, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o2.age - o1.age;
            }
        });

이 방식을 사용하면, int 자료형의 범위를 넘어가는 오류를 주의해야 합니다.

'Dev > Java & Spring' 카테고리의 다른 글

[Spring Boot] Exception: Required request body is missing  (0) 2022.01.24
[Java] JVM 메모리 구조  (0) 2022.01.01
[Spring] @RequestBody로 받아온 데이터가 null일 때  (0) 2021.11.18
[Spring] Spring Batch  (0) 2021.11.06
[Java] Stream  (0) 2021.10.05