It's easy, if you try
[JAVA] Comparable vs Comparator 본문
목차
1. Collections 의 Sort
2. Comparable
3. Comparator
4. Comparator 익명의 내부 클래스 사용하기
5. 람다식으로 표현하기
Collections.sort 사용하기
Collections.sort() 를 이용해 객체를 오름차순 또는 내림차순으로 정렬할 수 있다.
Arrays.sort()의 경우 Collection(List) 정렬은 불가능하다. 배열 객체의 경우만 가능하다.(기본은 오름차순, Arrays.sort(배열 이름, Collections.reverseOrder()); ==> 내림차순)
만약 사용자가 정렬 조건을 다시 정의하고 싶다면 1. Comparable (구현, compareTo 메소드 오버라이딩) 2. Comparator (구현, compare 메소드 오버라이딩) 두가지 방법으로 재정의할 수 있다.
Comparable
특징 : Collections.sort() 전달 인자가 1개 / 익명 클래스로 사용될 수 없음.
먼저 Comparable을 이용한 리스트 정렬을 알아보자.
class Person implements Comparable<Person>{
private String name;
private int age;
private String job;
private int score;
public Person(String name, int age, String job, int score) {
super();
this.name = name;
this.age = age;
this.job = job;
this.score = score;
}
@Override
public int compareTo(Person o) {
return age-o.age;
}
}
Person 객체가 있고 이들을 나이(age) 기준으로 정렬하고 싶다면 위와 같이 코드를 작성하면 된다.
1. implements Comparable<Person>
2. 반드시 구현해야할 함수(compateTo) 오버라이딩
내림차순으로 정렬하고 싶다면 compareTo 메소드를 아래와 같이 수정한다.
@Override
public int compareTo(Person o) {
return o.age-age;
}
즉, 자신의 age에서 넘어온 객체의 age를 뺀 값을 반환 ==> 오름차순
넘어온 객체의 age 에서 자신의 age를 뺀 값을 반환 ==> 내림차순 이다.
이제 main에서 이를 활용해 객체 age 기준으로 정렬해보자
1. Person[] 객체 age 기준 오름차순 정렬
public class SortTest {
public static void main(String[] args) {
Person []persons= { new Person("A", 11, "학생", 100), new Person("B", 15, "학생", 90), new Person("C", 12, "학생", 76), new Person("D", 10, "학생", 80), new Person("E", 12, "학생", 85)};
Arrays.sort(persons);
System.out.println(Arrays.toString(persons));
}
}
출력
[Person [name=D, age=10, job=학생, score=80], Person [name=A, age=11, job=학생, score=100], Person [name=C, age=12, job=학생, score=76], Person [name=E, age=12, job=학생, score=85], Person [name=B, age=15, job=학생, score=90]]
2. List<Person> 객체 age 기준 오름차순 정렬
public class SortTest {
public static void main(String[] args) {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("A", 11, "학생", 100));
list.add( new Person("B", 15, "학생", 90));
list.add(new Person("C", 12, "학생", 76));
list.add(new Person("D", 10, "학생", 80));
list.add(new Person("E", 12, "학생", 85));
Collections.sort(list);
System.out.println(list);
}
}
출력
[Person [name=D, age=10, job=학생, score=80], Person [name=A, age=11, job=학생, score=100], Person [name=C, age=12, job=학생, score=76], Person [name=E, age=12, job=학생, score=85], Person [name=B, age=15, job=학생, score=90]]
1 번과 동일하게 출력됨을 확인할 수 있다.
여기서 만약 age가 같을 때는 score 기준으로 내림차순 정렬하고 싶다면 어떻게 하면 될까?
compareTo 함수를 아래와 같이 수정하면 된다.
@Override
public int compareTo(Person o) {
if(age - o.age == 0) {
return o.score- score;
} else {
return age-o.age;
}
}
출력
[Person [name=D, age=10, job=학생, score=80], Person [name=A, age=11, job=학생, score=100], Person [name=E, age=12, job=학생, score=85], Person [name=C, age=12, job=학생, score=76], Person [name=B, age=15, job=학생, score=90]]
C 학생과 E 학생의 순서가 점수 기준으로 바뀐 것을 확인할 수 있다.
Comparator
특징 : Collections.sort() 전달 인자가 2개 / 익명 클래스로 주로 사용됨.
Comparator는 compare 메소드를 오버라이딩해 정렬 기준을 재정의한다.
class Person implements Comparator<Person>{
private String name;
private int age;
private String job;
private int score;
public Person() {
// TODO Auto-generated constructor stub
}
public Person(String name, int age, String job, int score) {
super();
this.name = name;
this.age = age;
this.job = job;
this.score = score;
}
@Override
public int compare(Person o1, Person o2) {
return o1.age-o2.age;
}
}
위는 age 기준 오름차순을 재정의 한 것이다.
1. implements Comparator<Person>
2. 반드시 구현해야할 함수(compare) 오버라이딩
내림차순으로 정렬하고 싶다면 compare를 아래와 같이 재정의한다.
@Override
public int compare(Person o1, Person o2) {
return -(o1.age-o2.age);
}
main 함수에서 age를 기준으로 오름차순 정렬하는 코드를 구현해보자.
public static void main(String[] args) {
Person []persons= { new Person("A", 11, "학생", 100), new Person("B", 15, "학생", 90), new Person("C", 12, "학생", 76), new Person("D", 10, "학생", 80), new Person("E", 12, "학생", 85)};
Arrays.sort(persons, new Person());
System.out.println(Arrays.toString(persons));
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("A", 11, "학생", 100));
list.add(new Person("B", 15, "학생", 90));
list.add(new Person("C", 12, "학생", 76));
list.add(new Person("D", 10, "학생", 80));
list.add(new Person("E", 12, "학생", 85));
Collections.sort(list,new Person());
System.out.println(list);
}
여기서 발견할 수 있는 큰 차이점은 Comparable 의 경우 Collections.sort() 를 사용할 때 전달인자가 한개이지만
Comprator의 경우에는 두개라는 점이다. 결과는 동일하다.
출력
[Person [name=D, age=10, job=학생, score=80], Person [name=A, age=11, job=학생, score=100], Person [name=C, age=12, job=학생, score=76], Person [name=E, age=12, job=학생, score=85], Person [name=B, age=15, job=학생, score=90]]
[Person [name=D, age=10, job=학생, score=80], Person [name=A, age=11, job=학생, score=100], Person [name=C, age=12, job=학생, score=76], Person [name=E, age=12, job=학생, score=85], Person [name=B, age=15, job=학생, score=90]]
Comparator 익명의 내부 클래스 사용하기
Comparator의 경우, 단 한번만 재정의 해도 되는 상황이라면 익명의 내부 클래스를 사용하여 표현하면 더욱 간편하게 사용할 수 있다.
이 경우 Person 객체가 Comparator를 implements 하지 않아도 된다.
(Comparable의 경우 비교 대상이 없으므로 익명의 내부 클래스 방식으로 사용할 수 없다.)
아래와 같이 사용된다.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class SortTest {
private static class Person{
private String name;
private int age;
private String job;
private int score;
public Person() { }
public Person(String name, int age, String job, int score) {
super();
this.name = name;
this.age = age;
this.job = job;
this.score = score;
}
}
public static void main(String[] args) {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("A", 11, "학생", 100));
list.add(new Person("B", 15, "학생", 90));
list.add(new Person("C", 12, "학생", 76));
list.add(new Person("D", 10, "학생", 80));
list.add(new Person("E", 12, "학생", 85));
Collections.sort(list,new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.age-o2.age;
}
});
System.out.println(list);
}
}
출력
[Person [name=D, age=10, job=학생, score=80], Person [name=A, age=11, job=학생, score=100], Person [name=C, age=12, job=학생, score=76], Person [name=E, age=12, job=학생, score=85], Person [name=B, age=15, job=학생, score=90]]
익명 클래스를 사용하는 경우에는 Person 클래스에 implements Comparator<Person> 을 구현하지 않고, main 함수의 Collection.sort 내에서 new 로 Comparator<Person>을 정의해 사용한다.
이는 람다식으로 더욱 간단하게 표현될 수 있다.
람다식으로 표현하기
Collections.sort(list, (o1, o2) -> {
return o1.score - o2.score;
});
'언어 > 자바(Java)' 카테고리의 다른 글
[Java] final 사용 방법 간단 정리 (static과의 차이점) (0) | 2021.09.15 |
---|---|
[Java] HashMap Comparator 람다식 정렬 (0) | 2021.07.06 |
[Java] 코드 개선을 위한 Collection 사용 (0) | 2021.07.02 |
[Java] 순열 / 조합 / 부분 집합 정리 (수도 코드 - 재귀편) (0) | 2021.02.15 |
[JAVA] 언어 개요 - 특징 (0) | 2021.02.14 |