DEV-STUDY/Java

[Java] 객체 배열 정렬

HwangJerry 2023. 7. 5. 10:50

객체는 여러 필드를 가지고 있을텐데, 어떤 특정 필드를 기준으로 오름차순 정렬을 하기 위해서는 여러가지 방법이 존재합니다.

 

@Override compareTo()

가장 원시적인 방법(지금은 잘 사용하지 않는 방법)은 클래스에 Comparable<> 인터페이스를 구현한다고 한 뒤에, compareTo() 함수를 Override하면 됩니다.

 

이 때, 현재 객체와 넘어오는 객체의 값을 비교하여, 값을 나타내주는 것에 따라 오름차순/내림차순이 결정됩니다.

1. this(현재 객체)가 비교 객체보다 뒤에 있어야 한다면 -> 오름차순 : 양수(1) /// 내림차순 : 음수(-1)

2. this(현재 객체)가 비교 객체보다 앞에 있어야 한다면 -> 오름차순 : 음수(-11) /// 내림차순 : 양수(1)

3. this(현재 객체)가 비교 객체와 동일하다면 -> 오름차순 : 0 /// 내림차순 : 0

 

이처럼, 오름차순으로 정렬하기 위해 기준이 되는 필드값은 무조건 int여야 합니다.

class Student implements Comparable<Student> {
    int kor, eng, math;

    public Student(int kor, int eng, int math){
        this.kor = kor;
        this.eng = eng;
        this.math = math;
    }

    @Override
    public int compareTo(Student student) { // 국어 점수 기준 오름차순 정렬
        if(this.kor > student.kor)
            return 1;
        else if(this.kor < student.kor)
            return -1;
        else
            return 0;
    }
};

위 과정은 다시 생각해보면 두 객체의 필드 값의 차로 구현할 수 있습니다.

@Override
public int compareTo(Student student) { // 국어 점수 기준 오름차순 정렬
    return this.kor - student.kor;
}

@Override
public int compareTo(Student student) { // 국어 점수 기준 내림차순 정렬
    return student.kor - this.kor;
}

 

만약 국어 점수가 동점일 경우 또 다른 기준으로 정렬을 구현하는 것은 조건문을 통해 쉽게 구현이 가능합니다. 오름차순과 내림차순을 섞어서도 구현이 가능합니다.

@Override
public int compareTo(Student student) {
    if(this.kor == student.kor)	 // 국어 점수가 일치한다면
        return this.eng - student.eng;  // 영어 점수를 기준으로 "오름차순" 정렬합니다.
    return this.kor - student.kor;	 // 국어 점수가 다르다면, 오름차순 정렬합니다.
}

@Override
public int compareTo(Student student) {
    if(this.kor == student.kor)	 // 국어 점수가 일치한다면
        return student.eng - this.eng;  // 영어 점수를 기준으로 "내림차순" 정렬합니다.
    return this.kor - student.kor;	 // 국어 점수가 다르다면, 오름차순 정렬합니다.
}

 

lambda + Arrays.sort()

자바8 이후부터는 람다를 지원하므로 Arrays.sort()에 인자로 정렬 함수를 넣어줘서 진행할 수도 있습니다. 이것의 장점은 위와 같이 클래스 내에 compareTo() 메서드를 번거롭게 override하지 않아도 된다는 것입니다. 여기서 a와 b 중에서는 a가 기존 compareTo 재정의 방식에서의 this를 의미하게 됩니다.

Arrays.sort(students, (a, b) -> a.kor - b.kor); // 국어 점수 기준 오름차순 정렬

 

이를 활용하여, 복잡한 정렬 조건을 설정하고 싶다면 Arrays.sort()의 두 번째 인자로 comparator를 정의해줄 수도 있습니다. 람다를 이용하는 경우에는 compare() 메서드를 재정의해야 합니다. 다음 예시는 Student 객체의 키를 기준으로 오름차순 비교를 위한 정의이므로 Student 클래스에 대하여 정의되어 있는 것을 확인할 수 있습니다.

 

주의할 점은, compareTo와 compare는 받는 인자의 개수가 다르다는 것입니다. compareTo는 객체 1개, compare는 객체 2개를 받습니다. 위와 마찬가지로 a가 this의 역할을 수행한다고 보면 됩니다.

// custom comparator를 활용한 정렬
Arrays.sort(students, new Comparator<Student>() {  
    @Override
    public int compare(Student a, Student b) { // 키를 기준 오름차순 정렬합니다.
        return a.height - b.height;
    }
});