자바스크립트 공부 할 때도 정렬이 서툴렀다.
그래서 헷갈리지 않게 제대로 정리하려고 한다.
Comparable - 원래 기준이 있는 정렬
Comparator - 원래 기준이 없어서 새로 기준을 만들어야 하는 정렬
Comparable
import java.util.Arrays;
public class sorting {
public static void main(String[] args) {
// TODO Auto-generated method stub
Student[] School = {
new Student("Tom",90),
new Student("Jim",112),
new Student("Mije",990),
new Student("Ann",390),
};
Arrays.sort(School);
System.out.println(Arrays.toString(School));
}
}
class Student implements Comparable{
int score;
String name;
Student(String name, int score){
this.name = name;
this.score = score;
}
public String getName() {
return this.name;
}
public String toString() {
return "["+name+","+score+"]";
}
public int compareTo(Object student) {
Student nexStudent = (Student)student;
System.out.println(
"현재 학생: "+this.name+ "다음 학생: "+nexStudent.getName());
return nexStudent.score-this.score;
}
}
다음은 Student객체의 성적순으로 정렬하는 코드이다.
추상 객체 인터페이스인 Comparable을 구체화 시키고
Object클래스 안에 들어 있는 compareTo 메소드를 오버라이딩하면서 정렬 기준을 만든다.
이때 파라미터는 무조껀 Object로 받아서 캐스팅 해주어야 한다.
어떤 순서로 정렬될까 궁금해서 출력을 해봤는데 다음과 같다.
현재 학생: Jim다음 학생: Tom
현재 학생: Mije다음 학생: Jim
현재 학생: Ann다음 학생: Mije
현재 학생: Ann다음 학생: Jim
현재 학생: Ann다음 학생: Mije
아마 자바의 여러가지 정렬 기준을 따라서 여러 값이 왔다 갔다 하면서 정렬 되는 것 같다.
결국 양의 수 대로 정렬이 된다.
(위의 예시 경우에는
Tom(90)-Jim(112) = 음
Jim(112) - Mije(990) = 음
Mije(990) - Ann(390) = 양
Jim(112) - Ann(390) = 음
Mije(990) - Ann(390) = 양
이기 때문에 Mije Ann Jim Tom 순이고 반대로 오름차순인 경우는
Jim(112)-Tom(90)- = 양
Mije(990)-Jim(112) = 양
Ann(390) - Mije(990) = 음
Ann(390) - Jim(112) = 양
Ann(390) - Mije(990) = 음
이다.)
만약 Comparable을 구체화하여 오버라이딩 하지 않는다면
다음과 같은 에러를 발생시킨다.
Comparator
import java.util.Arrays;
import java.util.Comparator;
public class sorting {
public static void main(String[] args) {
// TODO Auto-generated method stub
Student[] School = {
new Student("Tom",90),
new Student("Jim",112),
new Student("Mije",990),
new Student("Ann",390),
};
// Arrays.sort(School);
Arrays.sort(School, new NameSort());
System.out.println(Arrays.toString(School));
}
}
class NameSort implements Comparator{
public int compare(Object pre, Object next) {
Student preStudent = (Student)pre;
Student nextStudent = (Student)next;
return preStudent.name.compareTo(nextStudent.name);
}
}
class Student implements Comparable{
int score;
String name;
Student(String name, int score){
this.name = name;
this.score = score;
}
... 이하 생략
Comparable을 이용하여 compareTo로 정렬한 경우에는
sort 메소드에서 두번째 파라미터로 받을 Comparator를 생략하고
첫번째 파라미터인 오브젝트에서 Comparable인터페이스의 compareTo메소드에 따라 정렬하지만
sort 메소드에서 두번째 파라미터로 Comparator를 구체화한 클래스의 인스턴스를 입력시에는
이 클래스를 기준으로 정렬한다.
Comparator는
compare메소드를 오버라이딩해야하며
return은 compareTo()메소드를 이용하여, a.compareTo(b)와 같은 식으로 오브젝트를 비교한다.
이 때 compareTo는 a(이전값)이 클 때 양수를 뱉어낸다.
심화
만약 동점자가 있고 그에 동점일 경우에는 이름순으로 처리하고 싶을 땐 어떻게 하면 좋을까?
Student[] School = {
new Student("Tom",90),
new Student("Jim",112),
new Student("Mije",990),
new Student("Andrew",990),
new Student("Ann",390),
};
다음 예제의 결과는 다음과 같다.
public int compareTo(Object student) {
Student nextStudent = (Student)student;
if(this.score-nextStudent.score>0) {
return 1;
}
if(this.score-nextStudent.score<0) {
return -1;
}
if(this.score-nextStudent.score == 0) {
return this.name.compareTo(nextStudent.name);
}
return this.score-nextStudent.score;
}
하지만 compareTo메소드를 다음과 같이 수정하면 성적이 동점일 경우 이름순으로 출력된다.
만약 이전값이 다음값보다 크다면 양수를 아닐 경우엔 음수를 반환하고
동점일 경우에는 compareTo메소드를 이용하면 된다.
Comparator
class NameSort implements Comparator{
public int compare(Object pre, Object next) {
Student preStudent = (Student)pre;
Student nextStudent = (Student)next;
if(preStudent.score-nextStudent.score>0) {
return 1;
}
if(preStudent.score-nextStudent.score<0) {
return -1;
}
if(preStudent.score-nextStudent.score == 0) {
return preStudent.name.compareTo(nextStudent.name);
}
return preStudent.score-nextStudent.score;
}
}
역시 같은 로직을 이용하면 가능하다.
'Language > Java' 카테고리의 다른 글
[Java8] Strategy Pattern, FP, 1급 객체 (0) | 2019.04.14 |
---|---|
[Java]Collection 객체 응용(2) (0) | 2019.04.14 |
[Java]Collection 객체 응용(1) (0) | 2019.04.12 |
[Java] 자바 람다식 (0) | 2019.04.09 |
[Java]모던 자바 ? Java8 Stream을 응용한 리스트 정렬 (0) | 2019.04.09 |