Java Comparable, Comparator Interface (1)
by Dongy
Java로 개발을 하면서 배열이나 List 등의 Collection 프레임워크를 Arrays.sort(), Collections.sort()를 이용하여 정렬해본 경험이 있을겁니다.
Arrays.sort(), Collections.sort() 메소드가 Merge Sort, Insertion Sort, QuickSort 등 정렬 기법들을 구현하고 있다면,
오름차순으로 정렬할지 내림차순으로 정렬할지에 대한 정렬 기준은 Comparable, Comparator Interface가 정합니다.
Java는 정렬의 기준을 정할 수 있도록 Comparable과 Comparator라는 두 가지 Interface를 제공합니다.
Comparable - 기본 정렬(오름차순 정렬)할 때 사용합니다.
Compatator - 원하는데로 정렬 순서를 지정할 때 사용합니다.
Comparable - class 내부에서 정렬 기준을 지정할 때 사용합니다.
Compatator - class 외부에서 정렬 기준을 지정할 때 사용합니다.
우리가 사용했던 Arrays.sort(), Collections.sort() 가 오름차순 정렬을 해줄 수 있었던 이유는 Integer, String 등의 클레스에서 Comparable 를 구현하고 있으므로 자동으로 오름차순 정렬이 되었던 것이었습니다.
여기까지 읽어도 도통 무슨 소린지 이해가 안가더라도 괜찮습니다.
이해를 돕기 위해 Arrays.sort(), Collections.sort() 예제를 확인해보죠
Code
//Arrays.sort() 예제
int array[] = {4,3,5,6,-1,-2};
String array2[] = {"기아", "포르쉐", "현대", "벤츠", "도요타", "폭스바겐"};
//정렬
Arrays.sort(array);
Arrays.sort(array2);
//array[] 출력
int length = array.length;
for(int i = 0; i < length ; i++){
System.out.print(array[i] + " "); // 결과는 -2 -1 3 4 5 6로 오름차순 정렬
}
System.out.println();
//array2[] 출력
int length2 = array2.length;
for(int i = 0; i < length ; i++){
System.out.print(array2[i] + " "); // 결과는 기아 도요타 벤츠 포르쉐 폭스바겐 현대로 오름차순 정렬
}
위 예제에서 Arrays.sort(array), Arrays.sort(array2)는
int 와 String는 내부적으로 Comparable Interface을 구현하여 오름차순의 기준으로 정렬할 수 있는 것입니다.
이것이 Comparable 인터페이스는 기본 정렬(오름차순 정렬)할 때 사용한다는 말입니다.
이것이 class 내부에 정렬 기준을 지정할 때 사용한다는 말입니다.
Comparable 을 구현하고 있는 클래스들은 서로 비교할 수 있는 클래스들
예를들면 String, Integer, Date, File 같은 클래스들 입니다.
이번엔 배열이 아닌 List 형태로 sort() 를 구현해보면,
int 타입의 배열 을 List 로만 바꿨습니다.
List 는 Collection 프레임워크 이므로 Arrays.sort()가 아닌 Collections.sort() 를 이용해야 합니다.
Code
// Collections.sort() 예제
List<Integer> list = new LinkedList<>();
list.add(4);
list.add(3);
list.add(5);
list.add(6);
list.add(-1);
list.add(-2);
Collections.sort(list);
int size = list.size();
for(int i = 0; i < size ; i++){
System.out.print(list.get(i) + " "); // 결과는 -2 -1 3 4 5 6로 오름차순 정렬
}
이제부터는 기본 클레스가 아닌 우리가 만든 클레스로 정렬을 시도해보겠습니다.
Friend 라는 클래스를 하나 만들고, 객체배열 또는 List 을 이용해 sort를 해보려고 합니다.
Code
class Friend{
String name;
int height;
int weight;
public Friend(String name, int height, int weight){
this.name = name;
this.height = height;
this.weight = weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
public static void main(String[] args) {
List<Friend> friends = new ArrayList<>();
friends.add(new Friend("김동*", 184, 77));
friends.add(new Friend("민상*", 190, 70));
friends.add(new Friend("강성*", 200, 72));
Collections.sort(friends);
int size = friends.size();
for(int i = 0; i < size ; i++){
System.out.print(friends.get(i).name + " ");
}
}
Friend 클래스는 이름, 키, 몸무게 맴버변수를 가지고 있고 각각 setter와 getter를 선언해줬습니다.
Friend 객체를 배열이나 ArrayList 형태로 만들었을 경우, 위 자동차, 숫자 정렬 예제와 동일하게
Arrays.sort(), Collections.sort() 가 작동할까요?
오류가 발생합니다.
이유는 Friend 클래스가 Comparable Interface 를 구현하지 않아 어떤 기준으로 정렬할지 정하지 않았기 때문입니다.
Comparable Interface 를 구현하여 Friend 객체의 어떤 맴버변수를 기준으로 정렬할지 정해야 합니다.
Comparable Interface 를 구현(implements) 한 뒤 compareTo 메소드를 오버라이드하면 해결할 수 있습니다.
Code
class Friend implements Comparable<Friend>{
String name;
int height;
int weight;
public Friend(String name, int height, int weight){
this.name = name;
this.height = height;
this.weight = weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
@Override
public int compareTo(Friend friend) {
return name.compareTo(friend.getName());
// compareTo 메서드는 내부적으로 앞변수 - 뒷변수 합니다.
// 결과값이 + 면 앞 변수가 큰 수, 혹은 사전순으로 뒤에 오는 String으로 return 1 합니다.
// 결과값이 - 면 앞 변수가 작은 수, 혹은 사전순으로 앞에 오는 String으로 return -1 합니다.
// 결과값이 0 이면 두 변수가 같으므로 return 0 합니다.
//따라서 아래와 같이 구현하면 이름, 나이 등을 내림차순으로도 정렬할 수 있습니다.
//@Override
//public int compareTo(human o) {
// if (name.charAt(0) > o.name.charAt(0)) return -1;
// else if (name.charAt(0) < o.name.charAt(0)) return 1;
// else return 0;
//}
//
//@Override
//public int compareTo(human o) {
// if(age > o.age) return -1;
// else if(age < o.age) return 1;
// else return 0;
//}
}
}
먼저, Friend 클래스에 Comparable
compareTo 메서드를 오버라이드하였습니다.
compareTo 메서드는 매개변수로 Friend 객체를 받고,
리턴값으로는 Friend 객체의 name 변수와 비교하는 구문을 넣었습니다.
위와같이 수정하고 실행하면 결과가 강성* 김동* 민상* 순(오름차순)으로 정렬이 되는 것을 확인할 수 있습니다.
다시 한번 class 내부에서 정렬 기준을 지정할 때 사용한다는 말입니다.는 말을 확인했습니다.
String, Integer, Date, File 등과 같은 클래스들도 같은 방식으로 Comparable 을 구현하고 있습니다.
그렇다면 내림차순 정렬은 어떻게 해야할까요
Compatator Interface를 사용하면 원하는 순서대로 정렬 기준을 바꿀 수 있습니다.
이제 Compatator - class 외부에서 정렬 기준을 지정할 때 사용한다는 말입니다.가 무슨 말인지 알아보겠습니다.
위 Friend Class 소스와 어떻게 다른지 비교하며 살펴보죠.
Code
//Compatator 예제
class Friend {
String name;
int height;
int weight;
public Friend(String name, int height, int weight){
this.name = name;
this.height = height;
this.weight = weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
//Comparator Interface 구현한 MyComparator class 선언
class MyComparator implements Comparator<Friend>{
@Override
public int compare(Friend f1, Friend f2) {
// f1.getHeight - f2.getHeight 할 때,
if(f1.getHeight() > f2.getHeight() )
return 1;
else if(f1.getHeight() < f2.getHeight() )
return -1;
else
return 0;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
List<Friend> friends = new ArrayList<>();
friends.add(new Friend("김동*", 184, 77));
friends.add(new Friend("민상*", 190, 70));
friends.add(new Friend("강성*", 200, 72));
Collections.sort(friends, new MyComparator());
int size = friends.size();
for(int i = 0; i < size ; i++){
System.out.print(friends.get(i).name + " ");
}
}
위 Friend Class 소스와 다른 점들은
- Friend 클래스에 Comparable Interface 를 지웠습니다.
- MyComparator 클래스를 선언하고 Comparator
를 implements 하였습니다. - main 함수 내에 Collections.sort()의 두번째 파라미터로 MyComparator의 인스턴스를 만들어 넣었습니다.
아래와 같은 결과를 얻을 수 있습니다.
김동*:184 민상*:190 강성*:200
마지막으로 배운 내용을 정리해보겠습니다.
Arrays.sort() - 배열을 정렬합니다.
Collections.sort() - Collection 프레임워크를 정렬합니다.
Comparable - 기본 정렬(오름차순 정렬)할 때 사용합니다.
Compatator - 원하는데로 정렬 순서를 지정할 때 사용합니다.
Comparable - class 내부에 정렬 기준을 지정할 때 사용합니다.
Compatator - class 외부에서 정렬 기준을 지정할 때 사용합니다.
결국 Comparable과 Compatator의 차이는 아래와 같습니다.
1. class 내부에 기준을 만들어 두느냐 class 외부에 기준을 생성하느냐의 차이
2. compareTo(Object o) 메서드를 구현하느냐 compare(Object o1, Object o2) 메서드를 구현하느냐 차이
결과>
Subscribe via RSS