친구들과 알고리즘 스터디를 하다가, 2개 이상의 조건으로 정렬을 하는 문제에서 Comparable/Comparator를 사용할 일이 있었다.
(참고문제: 백준 1181번 단어정렬 문제 )
Comparable/Comparator 사용법이 익숙하지 않아서 이 포스팅에서 정리하려고 한다.
※ [참고] 이 포스팅에서 사용한 코드 전체는 아래의 Github url에서 보실 수 있습니다.
https://github.com/sujinlee0616/Algorithm/blob/master/JavaExercises/sujin/format/ComparableEx.java
<Comparable>
1. Comparable ?
- 기본적인 정렬(int/long 오름차순, String 사전순 정렬)을 구현할 때 사용한다.
- Java에서 제공하는 정렬 가능한 클래스들은 모두 Comparable 인터페이스를 구현하고 있으며, 정렬 시에 이 Comparable에 맞게 정렬이 된다.
ex) Arrays.sort(arr); // 배열 정렬
ex) Collections.sort(list); // list 정렬
- 정렬할 객체에 Comparable 인터페이스를 implements 한 후, compareTo() 메서드를 오버라이드하여 구현한다.
(--> 아래의 코드에서 class Book implements Comparable<Book>한 걸 볼 수 있음. )
- 기본적이지 않은 정렬 (int/long 내림차순, String 사전역순, 여러개의 기준으로 정렬 등)시에는 Comparable이 아니라 Comparator를 사용하는 것이 일반적이다. ㅋComparator 설명은 이 포스팅에 정리하였다.
예를 들어, 아래와 같은 리스트가 있다고 치자. 이 리스트는 Book 클래스로 구성되어 있는데, 이 Book 클래스는 title(책 제목), author(저자), company(출판사), year(출간년도)로 구성되어 있다.
( 단순한 list (int로만 구성되었거나하는 list)를 Comparator를 이용해서 정렬하는 예제는 다루는 블로그 글이 많아서, 이 글에서는 일부러 class로 이루어진 list로 예시를 들었다. )
import java.util.ArrayList;
import java.util.Collections;
public class ComparableEx {
public static void main(String[] args) {
ArrayList<Book> list = new ArrayList<Book>();
list.add(new Book("총균쇄", "제레미 다이아몬드", "문학사상", 2005));
list.add(new Book("총균쇄", "제레미 다이아몬드", "문학사상", 2000));
list.add(new Book("파타고니아, 파도가 칠 때는 서핑을", "이본 쉬나드", "라이팅하우스", 2020));
list.add(new Book("파타고니아, 파도가 칠 때는 서핑을", "이본 쉬나드", "라이팅하우스", 2010));
list.add(new Book("코스모스", "칼 세이건", "사이언스북스", 2010));
list.add(new Book("코스모스", "칼 세이건", "사이언스북스", 2001));
list.add(new Book("죽은 자의 집 청소", "김완", "김영사", 2020));
list.add(new Book("동물농장", "조지 오웰", "민음사", 2007));
list.add(new Book("동물농장", "조지 오웰", "민음사", 1988));
list.add(new Book("침묵의 봄", "레이첼 카슨", "에코리브르", 2011));
list.add(new Book("불안", "알랭 드 보통", "은행나무", 2012));
list.add(new Book("불안", "알랭 드 보통", "은행나무", 2018));
list.add(new Book("싯다르타", "헤르만 헤세", "민음사", 2002));
list.add(new Book("싯다르타", "헤르만 헤세", "민음사", 2005));
list.add(new Book("호모데우스", "유발 하라리", "김영사", 2017));
Collections.sort(list);
for(int i=0; i<list.size(); i++)
System.out.println(list.get(i).getYear()+", "+list.get(i).getTitle());
}
}
class Book implements Comparable<Book> {
private String title;
private String author;
private String company;
private int year;
public Book(String a, String b, String c, int d) {
this.title = a;
this.author = b;
this.company = c;
this.year = d;
}
public String getTitle() {
return title;
}
public int getYear() {
return year;
}
}
만약, 이 리스트를
1. 출판년도 오름차순으로 정렬하려면 어떻게 해야할까? --> ex1) 에서 설명
2. 책 제목 사전순으로 정렬하려면 어떻게 해야할까? --> ex2) 에서 설명
3. 책 제목 기준으로 사전순으로 정렬하되, 만약 책 제목이 동일하다면 출판년도 오름차순으로 정렬하려면 어떻게 해야할까?
--> ex3) 에서 설명
결론은 Comparable을 이용하면 된다. 사실 3번은 Comparator를 더 많이 쓰는 것 같긴하지만, Comparable로도 해결할 수 있다.
ex1), ex2), ex3)의 코드를 살펴보기 전에, Comparable에 대한 기초지식을 살펴보자.
2. Comparable이 사용하는 메소드
- int compareTo(Type obj)
--> public int compareTo(Type) 메소드를 구현하고, 내부에서 비교 처리 후 비교 결과를 int형으로 리턴한다.
3. compareTo 메소드 작성법
- 현재 객체 < 파라미터로 넘어온 객체 : 음수 리턴
- 현재 객체 == 파라미터로 넘어온 객체 : 0 리턴
- 현재 객체 > 파라미터로 넘어온 객체 : 양수 리턴
- 음수 또는 0이면 객체의 자리가 그대로 유지됨.
양수일 경우 두 객체의 자리가 바뀐다.
ex1) 출판년도 오름차순으로 정렬
class Book implements Comparable<Book> {
private String title;
private String author;
private String company;
private int year;
public Book(String a, String b, String c, int d) {
this.title = a;
this.author = b;
this.company = c;
this.year = d;
}
public String getTitle() {
return title;
}
public int getYear() {
return year;
}
// ex1) 출판년도(year) 오름차순
public int compareTo(Book obj) {
if (this.year == obj.year) {
return 0;
// 현재 객체 == 파라미터로 넘어온 객체 ==> 0 리턴
} else if(this.year < obj.year) {
return -1;
// 현재 객체 < 파라미터로 넘어온 객체 ==> 음수 리턴 ==> 자리 바뀌지 X ==> 오름차순
} else {
return 1;
// 현재 객체 > 파라미터로 넘어온 객체 ==> 양수 리턴 ==> 자리 바뀌지 O ==> 오름차순
}
}
}
출력 결과)
ex2) 책 제목 사전순으로 정렬
class Book implements Comparable<Book> {
private String title;
private String author;
private String company;
private int year;
public Book(String a, String b, String c, int d) {
this.title = a;
this.author = b;
this.company = c;
this.year = d;
}
public String getTitle() {
return title;
}
public int getYear() {
return year;
}
// ex2) 책 제목 사전 순
public int compareTo(Book o) {
int res = this.getTitle().compareTo(o.getTitle());
return res;
}
}
결과)
ex3) 책 제목 사전순으로 정렬. 만약 책 제목이 같을 경우, 출간년도 오름차순으로 정렬
class Book implements Comparable<Book> {
private String title;
private String author;
private String company;
private int year;
public Book(String a, String b, String c, int d) {
this.title = a;
this.author = b;
this.company = c;
this.year = d;
}
public String getTitle() {
return title;
}
public int getYear() {
return year;
}
// ex3) 책 제목 사전순으로. 책 제목이 같을 경우, 출간년도 오름차순으로. <== 보통 이렇게 정렬 조건 추가하는 경우에는 Comparator 더 많이 쓰는듯...
public int compareTo(Book o) {
int res = this.getTitle().compareTo(o.getTitle());
if(res==0)
res = this.getYear() - o.getYear();
// 현재 객체 출판년도 > 파라미터로 넘어온 객체 출판년도 ==> 양수 리턴 ==> 자리 바뀌지 O ==> 오름차순
return res;
}
}
결과)
'Programming > Back-end(Java, JSP)' 카테고리의 다른 글
[Java] Comparator 정리 - 사용법, 예시코드, 정렬기준 여러개일 때 (0) | 2020.08.14 |
---|---|
[Java] printf 출력서식 - %d, %f, %c, %s (0) | 2020.07.04 |
[Java] Annotation (0) | 2020.04.18 |
[JSP] JSTL 용법 (0) | 2020.04.05 |
[JSP] EL(Expression Language) 용법, 연산자 (0) | 2020.04.05 |
VO(DTO), DAO, Service 용어 설명 (0) | 2020.03.18 |
[JSP] 내장객체 (기본객체, Implicit Objects) (0) | 2020.03.12 |
[Java] 생활코딩 Java1 Method 강의 정리 (0) | 2020.01.20 |