처음 이 개념을 접했을 때는 뭐지.. 인터페이스는 뭐고, 객체는 뭐고 어떻게 쓰는 거지 했는데 공부하다 보니 인터페이스도 알게 되고, 객체도 알게 되니 '아! 이래서 이렇게 쓰는구나' 하고 깨달음을 얻었다. 그래서 혹시 만약 인터페이스나 객체 등 여기 관련된 어떤 개념을 모른다면 그부분을 먼저 배우면 빠르게 습득이 가능할 것입니다.
아마 위 개념을 모른다면 Arrays.sort( )을 호출하면 알아서 배열을 정리하는 것으로 생각을 하셨을 가능성이 높습니다. 사실 이 정렬기능은 Comparable의 구현에 의해 정렬되었던 것입니다. 정렬을 하려면 '기준'이 필요합니다. Comparator와 Comparable은 모두 인터페이스로 객체를 비교할 수 있도록 만들게 하고, 이것을 사용하려고하면 인터페이스니 선언된 메소드를 반드시 구현을 해야합니다.
public interface Comparator<T> {
int compare(T o1, T o2);
}
public interface Comparable<T> {
public int compareTo(T o);
}
Compartor 와 Comparable 의 실제 코드
위 코드를 보면 매개변수의 개수부터 다른것이 보일 것이다. Comparator는 두 매개변수 객체를 비교하는 것이고, Comparable은 자기 자신과 매개변수 객체를 비교합니다. 자세한건 아래에서 실제 예시를 통해 보여드리겠습니다.
compareTo( )의 반환 값은 Int 이지만 두 객체가 같으면 0, 비교하는 값보다 크면 양수 작으면 음수를 반환하도록 구현을 해야하고, compare( ) 도 객체를 비교해서 음수, 0, 양수 중 하나를 반환하도록 구현해야 합니다. (오른쪽이 크면 음수, 작으면 양수)
ex) 오름차순 7 > 5 => 자리바꿈 ( 왼쪽 값이 클 때)
ex) 내림차순 5 < 7 => 자리바꿈 ( 오른쪽 값이 클 때)
Comparable: 기본 정렬기준을 구현하는데 사용
Comparator: 기본 정렬 기준 외에 다른 기준으로 정렬하고자 할 때 사용
그래서 이 두개가 어떻게 사용되는지 예제를 직접 보여드리겠습니다.
class Student{
private String name;
private int korScore;
private int engScore;
private int mathScore;
public Student(String name, int korScore, int engScore, int mathScore) {
this.name = name;
this.korScore = korScore;
this.engScore = engScore;
this.mathScore = mathScore;
}
}
public class Example {
public static void main(String[] args) {
ArrayList<Student> classRoom = new ArrayList<>();
classRoom.add(new Student("김철수", 80, 60, 90));
classRoom.add(new Student("나영희", 90, 80, 60));
classRoom.add(new Student("다람쥐", 30, 40, 20));
//영어 점수 기준으로 오름차순 정렬한다면 어떻게..? 기준이 없다!
Collections.sort(classRoom);//에러
}
}
학생 객체가 있는데 영어 점수 기준으로 학생들을 정렬하고 싶은데 위와 같이 일반적인 sort를 사용하면 에러가 날 것이다. 정렬하는 '기준'을 알 수 없기 때문이다. 그래서 객체를 비교할 수 있게 정렬 기준을 Comparator 와 Comparable을 인터페이스를 사용하여 우리가 직접 구현을 해야 합니다.
[Comparable]
Comparable은 자기 자신과 매개변수 객체를 비교 한다.
import java.util.ArrayList;
import java.util.Collections;
class Student implements Comparable<Student>{
private String name;
private int korScore;
private int engScore;
private int mathScore;
public Student(String name, int korScore, int engScore, int mathScore) {
this.name = name;
this.korScore = korScore;
this.engScore = engScore;
this.mathScore = mathScore;
}
@Override
public int compareTo(Student o) {
// if (this.engScore > o.engScore) {
// return 1;
// } else if (this.engScore == o.engScore) {
// return 0;
// } else{
// return -1;
// }
return this.engScore - o.engScore;
}
public String getName() {
return name;
}
}
public class Example {
public static void main(String[] args) {
ArrayList<Student> classRoom = new ArrayList<>();
classRoom.add(new Student("김철수", 80, 60, 90));
classRoom.add(new Student("나영희", 90, 80, 60));
classRoom.add(new Student("다람쥐", 30, 40, 20));
Collections.sort(classRoom);
for (Student student : classRoom) {
System.out.println(student.getName());
}
}
}
출력: 다람쥐 김철수 나영희
위에서 설명하듯이 자신과 상대방과의 차이를 비교하여 크면 양수, 같으면 0, 작으면 음수를 반환하도록 구현을 하였다. 이렇게 구현을하면 영어 점수가 높을 수록 뒤에가 오름차순으로 구현 할 수 있다.
return (this.engScore - o.engScore) * -1;
내림차순으로 구하고 싶으면 결과값에 음수를 붙여 정렬을 반대로 만드는 것도 가능합니다.
[Comparator]
두 매개변수 객체를 비교
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
class Student {
private String name;
private int korScore;
private int engScore;
private int mathScore;
public Student(String name, int korScore, int engScore, int mathScore) {
this.name = name;
this.korScore = korScore;
this.engScore = engScore;
this.mathScore = mathScore;
}
public int getKorScore() {
return korScore;
}
public String getName() {
return name;
}
}
class KorScoreSort implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.getKorScore() - o2.getKorScore();
}
}
public class Example {
public static void main(String[] args) {
ArrayList<Student> classRoom = new ArrayList<>();
KorScoreSort korScoreSort = new KorScoreSort();
classRoom.add(new Student("김철수", 80, 60, 90));
classRoom.add(new Student("나영희", 90, 80, 60));
classRoom.add(new Student("다람쥐", 30, 40, 20));
Collections.sort(classRoom, korScoreSort);
for (Student student : classRoom) {
System.out.println(student.getName());
}
}
}
출력: 다람쥐 김철수 나영희
학급인원을 국어점수로 오름차순 정렬하는 '기준' 을 직접 구현했습니다. 하지만 이렇게 사용하면 나는 한번만 정렬을 사용할 건데, 불필요한 클래스와 변수가 생겨 코드가 길어 졌습니다. 이럴 때는 익명 객체(클래스)를 활용하면 됩니다.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
class Student {
private String name;
private int korScore;
private int engScore;
private int mathScore;
public Student(String name, int korScore, int engScore, int mathScore) {
this.name = name;
this.korScore = korScore;
this.engScore = engScore;
this.mathScore = mathScore;
}
public int getKorScore() {
return korScore;
}
public String getName() {
return name;
}
}
public class Example {
public static void main(String[] args) {
ArrayList<Student> classRoom = new ArrayList<>();
classRoom.add(new Student("김철수", 80, 60, 90));
classRoom.add(new Student("나영희", 90, 80, 60));
classRoom.add(new Student("다람쥐", 30, 40, 20));
//익명 클래스 사용
Collections.sort(classRoom, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getKorScore() - o2.getKorScore();
}
});
for (Student student : classRoom) {
System.out.println(student.getName());
}
}
}
출력: 다람쥐 김철수 나영희
위에서는 정렬 기준 클래스인 KorScoreSort를 만들어서 객체를 생성하여 번거로운 과정을 통해 사용했지만 Collections.sort 부분에 직접 정렬 기준을 재정의하여 사용했습니다.
결론은 둘다 정렬의 기준을 만들기 위해 사용되지만
- Comparable은 자기 자신과 파라미터로 들어오는 객체를 비교하는 것
- Comparator는 자기 자신의 상태가 어떻던 상관없이 파라미터로 들어오는 두 객체를 비교하는 것
비교한다는 것은 같지만 비교 대상이 다르다는 점 입니다.
'자바 (ref. 자바의정석)' 카테고리의 다른 글
Set, Map - JAVA (0) | 2022.03.09 |
---|---|
컬렉션 프레임워크(Collections Framework) - JAVA (0) | 2022.03.08 |
String 클래스 - JAVA (0) | 2022.02.24 |
인터페이스(interface) - JAVA (0) | 2022.02.21 |
다형성(polymorphsim) - JAVA (0) | 2022.02.18 |