반응형
Comparable 와 Comparator의 사용법
Comparable과 Comparator는 정렬과 관련된 인터페이스입니다.
(sort()라는 메서드와 관련이 있다고 보시면됩니다.)
배열이나 Collections 프레임워크 사용시 sort() 메서드를 사용하면 자동으로 정렬을 시켜줍니다.
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 32 | package practice; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; public class SortImpl { public static void main(String[] args) { String[] alphabetArray = { "d", "f", "a", "c", "z", "e"}; List<String> alphabetList = new ArrayList<>(); alphabetList.add("d"); alphabetList.add("f"); alphabetList.add("a"); alphabetList.add("c"); alphabetList.add("z"); alphabetList.add("e"); Arrays.sort(alphabetArray); Collections.sort(alphabetList); System.out.println("===== Array ====="); for(String str : alphabetArray) { System.out.print(str + " "); } System.out.println(); System.out.println("===== Collections ====="); for(String str : alphabetList) { System.out.print(str + " "); } } } | cs |
===== Array =====
a c d e f z
===== Collections =====
a c d e f z
위와 같은 결과를 얻을 수 있는건, String 클래스 내부적으로 Comparable이 구현되어 있기 때입니다.
그렇다면 객체(Object)를 정렬을 시키면 어떻게될까요?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class Book { private String name; private int price; public Book(String name, int price) { this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } } | cs |
테스트를 위해 Book 이라는 객체를 하나 생성해보았습니다.
Book 이라는 객체는 name(이름)과 price(가격)으로 구성되어있습니다.
1 2 3 4 5 6 7 | Book[] books = new Book[3]; books[1] = new Book("a book", 1000); books[2] = new Book("b book", 3000); books[3] = new Book("c book", 2000); Arrays.sort(books); | cs |
Book 객체를 Array에 담아 정렬을 해보면 다음과 같은 결과가 나옵니다.
Exception in thread "main" java.lang.ClassCastException: practice.Book cannot be cast to java.base/java.lang.Comparable
어찌보면 당연한 결과 입니다. 왜냐하면 비교 대상이 없기 때문입니다. 이럴때 객체의 비교기준을 정해서 정렬을 시켜줄때 Comparable 인터페이스가 필요합니다. Book 객체에 Comparable를 implements 한후 compareTo 메서드를 구현해주면 됩니다.
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 32 33 34 | public class Book implements Comparable<Book>{ private String name; private int price; public Book(String name, int price) { this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public String toString() { return "Book : [name = " + this.name + "], [price = " + this.price + "]"; } @Override public int compareTo(Book compareBook) { // 오름차순 //return this.price - compareBook.price; // 내림차순 return compareBook.price - this.price; } } |
위와 같이 Book 객체를 수정한 후 sort()를 수행해보면
Book : [name = b book], [price = 3000]
Book : [name = c book], [price = 2000]
Book : [name = a book], [price = 1000]
와 같이 price(가격)으로 정렬이 잘되는 것을 볼 수 있습니다.
그렇다면 만약에 name(이름)으로 정렬을 하고싶으면 어떻게할까요? 다른 기준들로 Book 객체를 정렬하고 싶다면 compareTo 메서드를 다시 재정의 해야할까요? 이럴때 사용되는게 Comparator 인터페이스입니다.
사용법은 sort() 메서드의 2번째 인자에 Comparator를 익명클래스로 전달하여 정렬기준을 재정의하면 됩니다.
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 | public class BookTest { public static void main(String[] args) { Book[] books = new Book[3]; books[0] = new Book("a book", 1000); books[1] = new Book("b book", 3000); books[2] = new Book("c book", 2000); Arrays.sort(books); for(Book book : books) { System.out.println(book); } Arrays.sort(books, new Comparator<Book>() { @Override public int compare(Book arg0, Book arg1) { return arg0.getName().compareTo(arg1.getName()); } }); for(Book book : books) { System.out.println(book); } } } | cs |
이런식으로 가능합니다.
위에 sort 는 Book 클래스의 compareTo 메서드를 사용하여 정렬이 되고, 밑의 경우에는 Comparator에서 정의한 새로운 정렬기준으로 정렬이 됩니다.
sort()를 사용할 때 Comparator를 지정하지 않았을 경우, 해당 객체안에 Comparable(compareTo)을 구현한 내용에 따라 정렬을 합니다.
즉, Comparable은 객체의 기본정렬기준을 구현하는데 사용하고 Comparator는 그 외의 정렬기준이 필요할때 구현해서 사용하면 됩니다.
반응형
'프로그래밍 노트 > JAVA' 카테고리의 다른 글
[JAVA] 컬렉션프레임워크(CollectionFramework) 1 (0) | 2018.07.02 |
---|---|
[JAVA] JVM 메모리구조 (0) | 2018.06.29 |
[JAVA] RSA를 이용한 전자서명 및 복호화 (0) | 2018.06.13 |
[JAVA] 명명규칙 (0) | 2018.04.08 |
[JAVA]Jave SE, Java EE, Java ME (0) | 2018.02.26 |