일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- 코딩테스트
- 알고리즘공부
- 알고리즘
- Spring
- 백준
- 스프링
- Lan
- BAEKJOON
- 구현
- 싸피
- 프로토콜
- 개발공부
- 자바
- 클라이언트
- IP
- 네트워크
- 전송계층
- 스프링 부트와 AWS로 혼자 구현하는 웹 서비스
- 정렬
- SSAFY
- 코딩공부
- TCP
- 네트워크모델
- DP
- 다이내믹프로그래밍
- Java
- 개발자
- cs공부
- 서버
- Dynamic Programming
- Today
- Total
오늘 하루, develop
자바 Comparator 간단 정리 (feat. 정렬) 본문
💡 소개
알고리즘 문제를 풀다 보면 특정 기준에 맞게 배열 또는 리스트의 요소를 정렬해야 하는 순간이 온다.
그때 이따금씩 활용하게 되는 것이 Comparator 인터페이스인데, 오랜만에 구현할 때마다 헷갈려서 블로그를 찾아보게 돼서 미래의 나를 위해 간단하게 정리하고자 한다.
이 글에서는 Comparator 인터페이스의 깊이 있는 내용보다는 (깊이 있는 내용은 더 좋은 블로그들에서 많이 다루고 있기에ㅎ) 알고리즘 문제 해결 시 알아야할 간단한 내용들을 작성하려고 한다.
💡 어떤 경우에 Comparator을 사용하면 될까?
내가 Comparator를 사용한 경우는 아래와 같다.
- Arrays.sort()
- Collection.sort()
- new PriorityQueue<>()
Comparator은 자료구조 내에서 정렬을 하는 "기준"을 제공하는 역할을 한다고 생각하면 된다.
int, String 과 같은 경우는 이미 기본적으로 오름차순으로 기준이 정해져 있지만,
나만의 기준으로 변경하고 싶거나, 기준이 없는 타입의 경우에는 Comparator를 사용하게 된다.
💡 Comparator 활용 방법
Comparator 인터페이스이기 때문에 구현을 해줘야 하는데, 실질적으로 구현해야 하는 메서드는 compare() 메서드 하나다.
(나머지는 이미 구현되어 있다. default 또는 static 메서드)
배열을 정렬하는 경우 Arrays.sort()를,
컬렉션(리스트 등)을 정렬하는 경우 Collections.sort()를 사용한다.
두 경우 모두 2개의 인자를 가진다.
1) 첫 번째 인자는 정렬 대상
2) 두 번째 인자는 정렬 기준 (Comparator 구현체)
* 두 번째 인자는 정렬 대상 클래스가 Comparator 또는 Comparable 구현하고 있다면 생략 가능하며 기본 기준으로 정렬된다. (주로 오름차순)
예시는 아래와 같다.
public static void main(String[] args) throws IOException {
List<Point> list = new ArrayList<>();
Collections.sort(list, new Comparator<Point>() {
@Override
public int compare(Point o1, Point o2) {
if (o1.x < o2.x) {
return -1;
}
if (o1.x > o2.x) {
return 1;
}
return 0; //o1.x == o2.x
}
});
}
public static class Point {
int x;
int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
Point 객체의 리스트인 list를 정렬하기 때문에 첫 번째 인자로는 list를 넣었다.
두 번째 인자로는 compare() 메서드를 구현한 익명 객체를 넣었다.
익명 객체란?
- 이름이 없는 객체이다.
- 다른 객체의 특정 구현 부분만 따로 사용하거나 부분적으로 기능을 일시적으로 바꿔야 할 경우 사용한다.
Anonymous an = new Anonymous() {
@Override
int get() { return a; }
};
이 클래스는 Anonymous 클래스가 아닌, Anonymous을 상속받은 하나의 새로운 클래스이다.
사실 알고리즘 문제만 풀 때는 어떻게 사용하는지만 알면 되니까 너무 걱정 안해도 된다!
결국 두 번째 인자는 Comparator를 구현한 새로운 클래스이다.
💡 구현 시 유의사항
1) 위 예시에 Point가 들어간 부분은 내가 정렬하려는 요소의 자료형이다.
2) 정렬하고 싶은 순서대로 쓰고 그 경우에 음수(-1 권장)를 반환한다.
compare(o1, o2) 메서드에서 음수를 리턴하면 요소의 자리를 바꾸지 않고 양수를 리턴하면 자리를 바꾸게 되는데, 나는 이게 늘 헷갈려서 이것만 기억한다.
"내가 원하는 순서대로 쓰고 무조건 -1을 리턴한다."
(값의 크기는 늘 o1 < o2이라고 생각하면 됨)
o1, o2 순으로 정렬하고 싶으면 o1 < o2 이면 return -1 이렇게 쓰면 된다. (>의 경우 1, ==의 경우 0 리턴)
o2, o1 순으로 정렬하고 싶으면 o2 < o1 이면 return -1 이렇게 쓰면 된다. (>의 경우 1, ==의 경우 0 리턴)
* return o1-o2 처럼 그냥 뺄셈으로 리턴하면 편하긴 하지만, overflow 발생할 수 있으니 조심해서 사용하자!
나는 신경 쓰고 싶지 않아서 조금 귀찮아도 그냥 안전하게 if문을 사용하는 편이다.
💡 정렬 조건이 2개 이상인 경우
간혹 정렬 조건이 2개 이상인 경우가 있다.
1번 조건 기준으로 오름차순으로 정렬한다. 1번 조건이 동일하다면 2번 조건을 기준으로 오름차순으로 정렬한다.
이 경우에는 if(o1==o2) 문 안에 똑같은 방법으로 2번 조건을 기입하면 된다.
아래 예시는 x좌표를 기준으로 정렬한 후, x좌표가 동일하다면 y 좌표를 기준으로 정렬하는 코드이다.
Collections.sort(list, new Comparator<Point>() {
@Override
public int compare(Point o1, Point o2) {
if (o1.x < o2.x) {
return -1;
}
else if (o1.x == o2.x) {
if (o1.y < o2.y) {
return -1;
} else if (o1.y > o2.y) {
return 1;
} else {
return 0;
}
}
return 1; // o1.x > o2.x
}
});
정렬 시 자주 활용하는 Comparator을 간단하게 정리해 보았다.
혹시 틀린 부분이 있거나 궁금한 점이 있다면 댓글로 알려주세요!
고럼 안녀엉-
'알고리즘' 카테고리의 다른 글
백준 16768번 - Mooyo Mooyo (java) (0) | 2024.07.19 |
---|---|
백준 1202번 - 보석 도둑 (java) (0) | 2024.07.12 |
백준 14719번 - 빗물 (java) (0) | 2024.07.11 |
백준 5052번 - 전화번호 목록(java) (0) | 2024.07.10 |
백준 1744번 - 수 묶기(java) (2) | 2024.07.05 |