ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Comparable 인터페이스를 구현할 때 비교자(Comparator) 이용하기
    Dev. Diary/Memo 2023. 9. 27. 16:17

    책 Effective Java에서 Comparable 인터페이스에 관한 내용을 다루는 부분을 읽다가, 유용할 것 같은 코드를 알게 되었다.
    클래스에서 Comparable 인터페이스를 구현하고, compareTo() 메서드를 만들어서 객체들끼리 비교하도록 만드는 것을 우선순위 큐를 이용하여 알고리즘 문제를 해결할 때 많이 사용했었다. 그런데 클래스가 비교해야 할 필드가 여러 개 있을 경우에, 각각의 필드를 하나하나 다 비교해가며 compareTo() 메서드를 구현해야 했었다. 아래는 BOJ 문제 강의실 2(1379)에서 사용된 클래스이다. 기존의 코드에서 클래스의 멤버들이 너무 자유분방해보여서 약간 수정했다.

    class Lecture implements Comparable<Lecture> {  
        private int id, startTime, endTime;  
        private Lecture(int id, int startTime, int endTime) {  
            this.id = id;  
            this.startTime = startTime;  
            this.endTime = endTime;  
        }  
        public static Lecture create(int id, int startTime, int endTime) {  
            return new Lecture(id, startTime, endTime);  
        }  
        @Override // 강의 시작 시간이 빠른 것부터 나열하도록 우선순위 설정  
        public int compareTo(Lecture otherLecture) {  
            if (this.startTime == otherLecture.startTime) {  
                if (this.endTime == otherLecture.endTime) {  
                    return this.id - otherLecture.id;  
                } else return this.endTime - otherLecture.endTime;  
            } else return this.startTime - otherLecture.startTime;  
        }  
    }

    compareTo() 메서드만 보면 각각의 필드를 하나하나 비교하고 있다. 이 코드를 쓸 때도 좀 더 깔끔하게 쓸 수는 없을지 잠깐 생각했던 것 같은데, 그렇게 깊이 고민하지는 않았다. 책에서는 아래와 같은 코드를 추천해줬다.

    import java.util.Comparator;
    
    import static java.util.Comparator.comparingInt;
    
    class Lecture implements Comparable<Lecture> {  
        private final int id, startTime, endTime;  
        private static final Comparator<Lecture> COMPARATOR =  
            comparingInt((Lecture l) -> l.startTime)  
                .thenComparingInt(l -> l.endTime)  
                .thenComparingInt(l -> l.id);  
        private Lecture(int id, int startTime, int endTime) {  
            this.id = id;  
            this.startTime = startTime;  
            this.endTime = endTime;  
        }  
        public static Lecture create(int id, int startTime, int endTime) {  
            return new Lecture(id, startTime, endTime);  
        }  
        @Override  
        public int compareTo(Lecture otherLecture) {  
            return COMPARATOR.compare(this, otherLecture);  
        }  
    }

    위의 코드에서는 클래스의 필드가 그렇게 많지 않아서 크게 차이가 없어보이지만, 필드가 더 많이 있을 때는 Comparator를 사용하는 것이 코드를 쓰기도 좋고 보기도 좋을 것 같다. 약간의 성능 저하가 있다고는 하는데, 조건문 여러 개를 붙이는 것보다는 나을 것 같다.

    댓글

Designed by Tistory.