일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- programmers
- 자바
- 내일배움캠프
- greedy
- 스파르타내일배움캠프
- github
- 탐욕알고리즘
- 스파르타내일배움캠프TIL
- 그리디알고리즘
- 코딩테스트준비
- Django
- 롤
- 백준
- 알고리즘
- sort
- drf
- 그리디
- API
- Riot
- python
- 라이엇
- java
- 리그오브레전드
- SQL
- git
- 코딩테스트
- 프로그래머스
- 장고
- 파이썬
- lol
- Today
- Total
Lina's Toolbox
[Java] 특정 기준으로 정렬하는 법 (Comparator인터페이스 사용) / 제네릭 타입 본문
https://kimwoolina.tistory.com/128
🔼 이 문제를 풀면서,
파이썬의 sorted(numbers, key=functools.cmp_to_key(custom_compare)) 처럼,
자바에도 내가 만든 특정한 기준으로 정렬을 할 수 있게 만들어주는 기능이 있지 않을까 하여 찾아보았다.
Collections.sort(people, new Comparator<Person>() { // 제네릭 타입 Person(custom class)
@Override
public int compare(Person p1, Person p2) { // 메서드 인자의 타입도 Person
return p2.age - p1.age; // 리턴 타입은 int
}
});
<Person>은 제네릭 타입이다.
이 제네릭 타입은 Comparator가 어떤 타입의 객체를 비교하는지를 명시합니다.
- Comparator<Person>
Comparator가 Person 객체를 비교할 것임을 명시한다. 이는 두 개의 Person 객체를 비교하게 된다는 것을 뜻함. - compare(Person p1, Person p2): compare() 메서드는 Person 타입의 두 객체를 인수로 받는다.
- return p2.age - p1.age: compare() 메서드는 두 Person 객체를 비교하고, 그 결과를 int로 반환한다.
리턴 타입이 int인 이유는 비교 결과가: (이건 파이썬과 같네!)- 음수: 첫 번째 객체가 두 번째 객체보다 작음.
- 양수: 첫 번째 객체가 두 번째 객체보다 큼.
- 0: 두 객체가 같음을 의미.
제네릭이 없는 경우 (Collections.sort)
Collections.sort() 메서드에서 만약 제네릭을 사용하지 않으면, 자바는 기본적으로 모든 객체를 Object 타입으로 취급한다.
제네릭을 사용하지 않는 경우:
Collections.sort(people, new Comparator() { // 제네릭을 사용하지 않음
@Override public int compare(Object o1, Object o2) {
Person p1 = (Person) o1; Person p2 = (Person) o2;
return p2.age - p1.age;
}
});
- 여기서 문제점은 compare 메서드에서 Object 타입을 Person으로 명시적으로 형변환해야 한다는 것!
- 만약 형변환이 잘못되거나 잘못된 타입이 들어오면 런타임 오류가 발생할 수 있다.
💡 신기한점은 return (str1 + str2).compareTo(str2 + str1);를
return (str2 + str1).compareTo(str1 + str2);
로 바꿔주면 대소관계를 반대로 비교한다는 것이였다.
비교 순서만 바꿔주는 게 아닌가..? 했는데,
비교 순서를 바꾸는 것만으로도 정렬 방식이 바뀌었다.
return (str1 + str2).compareTo(str2 + str1);
(str1 + str2)가 (str2 + str1)보다 클 경우, num1이 num2보다 크다는 것을 의미.
즉, num1이 더 앞에 오게 된다.
이 경우 더 작은 수가 먼저 배치됨
수정된 비교 방식
return (str2 + str1).compareTo(str1 + str2);
이 방식에서는 (str2 + str1)이 (str1 + str2)보다 클 경우, num2가 num1보다 크다고 판단한다.
즉, num2가 더 앞에 배치되어 더 큰 수를 생성하게 된다.
예를 들어 num1 = 9와 num2 = 34라고 가정해보면:
- 기존 비교:
- (str1 + str2): 934
- (str2 + str1): 349
- 934 > 349 이므로 num1이 먼저 배치된다.
- 수정된 비교:
- (str2 + str1): 349
- (str1 + str2): 934
- 349 < 934 이므로 num2가 먼저 배치된다.
이렇게 비교 방식을 바꾸는 것만으로 원하는 정렬을 구현할 수 있었다.
간단한 변경으로 큰 수를 만들 수 있는 정렬 방식이 가능해지는 것!
🤔 혹은 파이썬 처럼
sorted_numbers = sorted(numbers, key=functools.cmp_to_key(custom_compare), reverse=True)
여기서 reverse=True같은 기능은 없을까?
Comparator와 Reverse Order 사용
정렬을 내림차순으로 진행하고 싶다면, Comparator를 사용하여 정렬 후,
Collections.reverse(numList)로 결과를 뒤집는 방법도 있다!
// 특정 기준으로 정렬 (내림차순)
Collections.sort(numList, (num1, num2) -> {
String str1 = Integer.toString(num1);
String str2 = Integer.toString(num2);
return (str1 + str2).compareTo(str2 + str1);
});
// 정렬된 리스트를 반전
Collections.reverse(numList);
'프로그래밍 언어 > Java' 카테고리의 다른 글
[Java] StringBuilder를 사용하는 이유 (1) | 2024.10.01 |
---|