[Java] Collections.sort // Comparable+CompareTo 와 Comparator 를 이용한 정렬
1) Collections.sort
기본적으로 ArrayList 를 정렬할 때, Collections.sort 를 이용한다.
Collections.sort 의 디폴트 값은 오름차순 정렬이고,
만약 내림차순 정렬을 원한다면 Collections.reverseOrder() 을 입력해주어야 한다.
이 디폴트값은 사실 이미 Collections이라는 클래스를 만든 사람이 미리 정해놓은 정렬값이다.
그렇기 때문에 사용자가 임의로 만든(Coffee 객체) 객체는 일반적인 Collections.sort 로는 작동하지 않는다.
에러가 발생한다.
따라서 유저가 임의로 만든 객체를 정렬하고 싶다면,
1) Comparable 인터페이스의 CompareTo 메소드를 오버라이딩하거나
2) Comparator 인터페이스의 Compare 메소드를 오버라딩 하는 방법이 있다.
2) Comparable 인터페이스의 CompareTo 메소드 사용하기.
CafeMenu 라는 출력 클래스를 만든 후, Coffee 라는 이름의, 유저가 정한 객체를 매개변수로 하는 ArrayList 객체를 생성했다.
implements Comparable <매개변수=Coffee> 라는 인터페이스를 상속하는 Coffee 라는 새로운 클래스를 생성했다.
그 후 클래스명과 동일한 Coffee 라는 생성자를 만들고, coffeeName 과 CoffeePrice 라는 매개변수를 담았다.
마지막으로 Comparable 이라는 인터페이스에 등록되어있는 추상 메소드인 compareTo 라는 메소드를 오버라이딩으로 가져온 뒤, compareTo ( 매개변수를 Coffee coffee ) 로 설정하였다.
compareTo 메소드의 비교는 merge sort 를 사용한다, 라고 인터넷 탐색을 하던 도중 발견하였지만, 지식이 그정도까지 미치지는 못하기 때문에 우선 공식적으로 외우려고 한다.
원시 자료형의 비교는 -1, 0, 1 과 같이 숫자의 크기로 비교할 수 있다.
따라서 getCoffeePrice() 로 불러오는 주체 객체에서 coffee(매개변수).getCoffeePrice() 매개변수 객체 를 뺸 값이
-1 이라면, 주체객체가 더 작다는 의미. 따라서 정렬 상으로는 앞으로 가게 된다.
0 이라면, 그 값이 같다는 의미이기 때문에 sort 가 발생하지는 않는다. 다만 객체의 매개변수가 2개 이상일 경우에는
위의 코드와 같이 if를 바탕으로 값이 같을 경우 이름을 기준으로 정렬한다 와 같은 케이스를 준다.
1 이라면, 반대로 주체객체가 매개변수 객체보다 값이 크다는 의미이다. 따라서 정렬 상으로는 뒤로 가게 된다.
3) Comparator 인터페이스의 Compare 메소드 사용하기.
두번째로 Comparator 인터페이스의 compare 이라는 메소드를 사용하는 방법이 존재한다.
Compare( 객체1, 객체2 ) 의 매개변수를 받는 메소드를 구현하게 된다.
그 후 객체1.비교값 vs 객체2.비교값 을 실시하게 된다.
사실 comparable 인터페이스의 compareTo 메소드를 사용하는 방법과
comparator 인터페이스의 compare 메소드를 사용하는 방법은
로직 상으로는 동일하다.
implements Comparble / compareTo(매개변수 객체) | comparator 익명객체 / compare(객체1, 객체2) |
주체객체의 비교값 vs 매개변수객체.비교값 | 객체1.비교값 vs 객체2.비교값 |
의 형태가 되는 것이다.
* 익명객체
익명객체 라는 용어가 등장했다. 익명객체는 위의 코드에서는 cofprice 라고 명명된 객체를 의미한다.
comparator 인터페이스에서만 익명객체가 등장하는 이유가 있다.
값을 비교하는 과정을 비교해보면 그 이유를 알 수 있다.
compareTo 메소드는 자기자신을 비교 대상으로 삼는다. 즉 직관적으로 알아볼 수 있다.
이미지상으로 보면, a객체 안의 compareTo 메소드( b객체 ) 를 비교한다. b.compareTo(c) 역시 마찬가지이다.
즉 비교 대상이 직관적으로 눈에 보이고, 불필요한(?) 객체의 생성이 없어진다.
compare 메소드는 Coffee 라는 객체 안에서 이루어진다.
따라서 Coffee객체명.compare() 의 형태가 된다.
하지만 막상 비교대상은 compare(매개변수객체1, 매개변수객체2) 이다.
즉 compare() 메소드가 구현되는 객체명과 상관없이 compare() 괄호 안의 객체 간의 비교가 발생하게 된다.
그 결과 위 코드와 같이 매우 직관성이 떨어지는 코드들이 발생한다.
이 점을 방지하기 위해 익명객체를 생성한 뒤, 그 속에서 comparator 인터페이스와 compare 메소드를 구현한다.
https://st-lab.tistory.com/243
자바 [JAVA] - Comparable 과 Comparator의 이해
아마 이 글을 찾아 오신 분들 대개는 Comparable과 Comparator의 차이가 무엇인지 모르거나 궁금해서 찾아오셨을 것이다. 사실 알고보면 두 개는 그렇게 어렵지 않으나 아무래도 자바를 학습하면서 객
st-lab.tistory.com
main 메소드 밖에, static 혹은 public static 으로 익명 객체를 구현해도 된다.
이 점이 comparator 인터페이스의 차별화된 장점이다.
다양한 기준의 정렬기준 comparator 인터페이스 compare 메소드를 구현한 뒤 익명객체만을 바꿔가며 메인 메소드에서 sort 를 해줄 수 있다는 점이다.
'Java' 카테고리의 다른 글
[Java] Collection 프레임워크(2) - Set(HashSet, TreeSet) (0) | 2022.03.02 |
---|---|
[Java] Collection 프레임워크(1) - List(LinkedList, Stack, Vector, ArrayList) (0) | 2022.03.02 |
[Java] Arrays.sort / list.sort / Collections.sort / 정렬하는 방법 정리 (0) | 2022.02.17 |
[Java] 메소드 사용에 있어서의 break, return 의 차이점 (0) | 2022.02.15 |
[Java] 자바의 인터페이스 : 상수와 추상 메소드. 추상 클래스와의 차이점, 오버라이딩 (0) | 2022.02.10 |