반응형

객체를 ordering 하는 방법에 대해 알아본다.

 

Comparable interface

  • 객체의 natural ordering 에 대해 정의할 수 있음
  • 클래스 안에서 클래스끼리 비교할 때 override해두면 Collections.sort, Arrays.sort 등에서 사용됨
  • 하나뿐인 아래 함수를 상속받고 구현하면 됨, 구현해야지만 사용할 수 있음(not functional interface)
public int compareTo(T o);
  • 해당 함수로 현재 객체(this)와 다른 객체(o)를 비교할 수 있으며 반환 값은 아래와 같음
    • this < o : -1    정방향
    • this == o : 0
    • this > o : 1     역방향
  • 참고로 String 객체는 해당 interface의 함수를 이미 구현하고 있어서 별도의 설정을 하지 않아도 알파벳 순 정렬을 할 수 있다.

String.java

import java.util.*;

@Getter
@ToString
@AllArgsConstructor
public class Person implements Comparable<Person> { ///
    private String name;
    private int age;

    @Override
    public int compareTo(Person other) { ///
        return Integer.compare(this.age, other.age); // Natural order by age
    }



    // Main method for testing
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
            new Person("Alice", 30),
            new Person("Bob", 25),
            new Person("Charlie", 35)
        );

        // Sort using the natural order defined by Comparable
        // 안줘도 자동으로 있는거 사용
        Collections.sort(people);

        System.out.println("Sorted by age (natural order): " + people);
    }
}

 

Comparator Interface

  • Comparator is intended to be used for defining external comparison logic rather than internal natural ordering. However, you can create a Comparator for Person as a separate class, an inner class, or even as a static field in the Person class to provide custom sorting criteria.
  • 객체 자체의 natural ordering 이 없거나, 좀 더 복잡한 정렬 방법이 있을 경우 사용(flexibility)
  • 아래 함수를 상속받고 구현하면 됨(functional interface) ; 람다로 사용가능
int compare(T o1, T o2);
  • int를 반환하도록 되어있는데, 비교 값은 아래와 같다.
    • 앞 < 뒤 : -1    정방향
    • 앞 == 뒤 : 0
    • 앞 > 뒤 : 1     역방햐
  • String 객체에 역시 이미 정의 되어 있다.

String.java

기본함수

 

  • Comparator<T> reversed():
    • Returns a comparator that reverses the order of this comparator.
  • Comparator<T> thenComparing(Comparator<? super T> other):
    • Returns a comparator that first compares using this comparator, and if the comparison is equal, uses the provided comparator. 앞에 비교한 결과가 같으면 추가 사용!

 

import java.util.*;

@Getter
@ToString
@AllArgsConstructor
public class Person { //여기서 comparator implement못하고 별도의 클래스로 빼야 함
    private String name;
    private int age;


    // Main method for testing
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
            new Person("Alice", 30),
            new Person("Bob", 25),
            new Person("Charlie", 35)
        );

        // Sort by name
        // 별도로 만들어서 사용 , 람다 사용가능
        Comparator<Person> nameComparator = Comparator.comparing(Person::getName);
        Collections.sort(people, nameComparator);
        System.out.println("Sorted by name: " + people);

        // Sort by age in reverse order
        Comparator<Person> ageComparator = Comparator.comparingInt(Person::getAge).reversed();
        Collections.sort(people, ageComparator);
        System.out.println("Sorted by age (reverse order): " + people);
    }
}
//or 아래처럼 함수로 빼고 new AgeComparator() 삽입
   // Comparator for sorting by age
    public static class AgeComparator implements Comparator<Person> {
        @Override
        public int compare(Person p1, Person p2) {
            return Integer.compare(p1.getAge(), p2.getAge());
        }
    }

 

어떤 것을 사용해야 하나

The Comparable interface is a good choice to use for defining the default ordering, or in other words, if it’s the main way of comparing objects.

기본적으로는 Comparable 을 사용하고 아래와 같은 경우 Comparator을 사용

  • 파일이 수정 불가하여 interface를 구현할 수 없는 경우 Comparator 사용
  • 비교 로직을 분리해서 관리해야하는 경우 Comparator 사용
  • 비교 전략이 다양해서 Comparable 로 부족할 경우 Comparator 사용

 


참고

https://www.baeldung.com/java-comparator-comparable

728x90
반응형

+ Recent posts