[자바] Comparable 인터페이스로 값 정렬하기
Comparable
값을 비교할 때 사용하는 이 두가지는 모두 "인터페이스"이다.
각각의 추상메서드를 갖고있는 이 인터페이스들은 implements해서 사용하며, 반드시 해당 추상메서드를 implements하는 클래스 내부에서 구현해야한다.
https://imcoding.tistory.com/10
인터페이스(Interface) .java
인터페이스(Interface) 인터페이스는 하나의 추상적 개념이다. 가령 자동차를 예시로 들어보자. 자동차의 사전 뜻은 다음과 같다. 자동차 (自動車) [명사] 원동기를 장치하여 그 동력으로 바퀴를 굴
imcoding.tistory.com
그렇다면 왜 해당 인터페이스를 사용할까?
primitive 타입의 데이터도 부등호만으로 비교가 가능한데 말이다.
만약 우리가 primitive 타입이 아닌, Map이나 클래스 객체와 같이 두 가지의 요소를 갖는 경우를 비교해야한다고 생각해보자.
class Student{
int age;
int score;
Student(int age, int score) {
this.age = age;
this.score = score;
}
}
위와 같이 학생 클래스를 만들고 그 안에 나이과 점수를 뜻하는 매개변수를 각각 생성했다.
여러 학생이 있을 때 각 학생들을 단순 비교한다면 나이와 점수 중 어떤 것을 기준으로 정렬될까?
이럴 때 비교를 수월하는 방법이 Comparable 인터페이스를 사용하는 것이다.
지금부터 Comparable 사용법을 알아보겠다.
매개변수 값을 받아서 자기 자신과 비교한다.
선언하는 방법은 아래와 같다.
class Student implements Comparable<Student> { // 1. 클래스 선언
@Override
public int compareTo(Student o) { // 2. 오버라이딩
return 0;
}
}
먼저 클래스를 생성할 때는 상속에서는 extends였다면, 여기서는 implements를 사용한다.
그리고 Comparable 뒤에는 비교대상의 <제너릭 타입>이 쓰여야한다.
여기서는 Student 객체와 비교할 것이니 Student를 넣었다.
생성했으면 처음에는 빨간색으로 밑줄이 그어질것이다.
인터페이스는 추상메서드를 가지고 있고, implements 한 클래스는 해당 추상메서드를 반드시 구현해야하기 때문이다.
그것이 바로 public int compareTo()라고 보면 되겠다.
코드를 좀 더 작성해보겠다.
class Student implements Comparable<Student> {
int age;
int score;
public Student(int age, int score) {
this.age = age;
this.score = score;
}
@Override
public int compareTo(Student o) {
return this.age - o.age;
}
}
class Note{
public static void main(String[] args) {
Student A = new Student(7,80);
Student B = new Student(16, 70);
System.out.println(A.compareTo(B));
}
}
Student의 생성자를 생성해주었다.
이제 Student의 매개변수로 들어오는 this.age와 this.score를 가지고 compareTo를 통해 들어오는 파라미터 o와 비교 후 값이return된다고 보면 된다.
그리고 여기서 A.compareTo(B)를 해주면 단순히 A의 age가 this.age가 되고 B의 age가 o.age가 되어서 두 값의 차이를 반환해줄 것이다.
먼저 들어가는 매개면수가 this.age가 된다고 생각하면 편할것이다.
하지만 우리가 Comparable 인터페이스를 사용하는 이유는 단순히 두 값의 차이를 알기 위해서가 아니다.
그럴거였으면 다른 방식으로 얼마든지 가능하기 때문이다.
Comparable 인터페이스는 값 정렬에 사용할 수 있다.
아래 코드를 보자.
class Student implements Comparable<Student> {
int age;
int score;
public Student(int age, int score) {
this.age = age;
this.score = score;
}
@Override
public int compareTo(Student o) {
return this.age - o.age;
}
}
class Note{
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<>();
list.add(new Student(17, 70));
list.add(new Student(16, 70));
list.add(new Student(19, 40));
Collections.sort(list);
for (Student student: list) {
System.out.println(student.age + " " + student.score);
}
}
}
각 학생마다 age, score 순으로 데이터를 넣었다.
그리고 이를 리스트에 담고 Comparable 인터페이스를 implements한 Student 메서드를 통해서 정렬 방식을 설정해주었다.
위에서 this.age - o.age로 두 값의 차이가 반환된 것과 다르게, 여기서는 age를 기준으로 오름차순으로 정렬된다.
만약 o.age - this.age로 작성한다면? age를 기준으로 내림차순 정렬된다.
출력
16 70
17 70
19 40
이를 좀더 응용하면 아래처럼 가능하다.
class Student implements Comparable<Student> {
int age;
int score;
public Student(int age, int score) {
this.age = age;
this.score = score;
}
@Override
public int compareTo(Student o) {
return this.score == o.score ? this.age - o.age : o.age - this.age;
}
}
return값을 위 코드처럼 작성하면 어떻게 출력될 것 같은가? 이제 충분히 예상이 갈 것이다.
출력 결과를 보겠다.
출력
19 40
16 70
17 70
그렇다. score가 같을 경우에는 오름차순, 그렇지 않다면 내림차순으로 정렬된 모습이다.
여기까지 Comparable 인터페이스와 그의 추상메서드인 compareTo를 이용하여 조건하에 정렬하는 법을 알아보았다.