컬렉션 정렬 예시
ex) 만약 학생 리스트라면
-> 리스트내에서 학생객체들을 학번, 이름, 생년월일, 성적, 키 등을 기준으로 정렬할 수 있다.
sort 함수의 이해
형태
class collections{
public static <T extends Comparable<T>> void sort(List<T> list){ ....
}
콜렉션에는 Comparable을 상속받는 제네릭타입 T객체를 이용하여 정렬하도록 되어있다.
제네릭 T를 통해서 매개변수나 반환형의 타입을 자유롭게 지정할 수 있다.
"그렇다면 Comparable 인터페이스는 무엇인가?"
객체정렬의 두가지 방법
1. Comparable 인터페이스
형태interface Comparable<E>{ int compareTo(E other);}타입 매개변수 E는 this와 같은 타입이고
this가 크면 return 1, 같으면 return 0, 작으면 return -1의 성질을 가지도록 만든다.
예시1)
class Pair implements Comparable<Pair>{
int x;
int y;
@Override
public int compareTo(Pair other){
return this.x - other.x;
}
}
// main부
ArrayList<Pair> pairList = new ArrayList<>();
Collections.sort(pairList); // pairList에 객체들이 있다고 가정
x와 y필드를 가져서, 좌표를 가리키는 객체 Pair가 있다.
제네릭 타입 E자리에는 Pair가 들어온 상황이고, Comparable을 implements 했기 때문에 compareTo를 오버라이드 해줘서 원하는 대로 정렬할 수 있도록 compareTo를 구현한다.
return this.x - other.y의 예시는 x기준으로 오름차순 정렬하겠다고 하는 것이다.
예시2)
class Pair implements Comparable<Pair>{
int x;
int y;
@Override
public int compareTo(Pair other){
if(this.x > other.x){
return 1;
}
else if(this.x < other.x){
return -1;
}
else{
if(this.y > other.y){
return 1;
}else if(this.y < other.y){
return -1;
}
return 0;
}
}
// main부
ArrayList<Pair> pairList = new ArrayList<>();
Collections.sort(pairList); // pairList에 객체들이 있다고 가정
x를 기준으로 오름차순 후, 같다면 y를 기준으로 오름차순 하는 코드이다.
2. Comparator 인터페이스
Comparable는 this.compareTo(other) 형태여서 this와 다른 객체를 비교하는 것이었다면
comparator는 int compare(x,y)를 통해서 x,y를 비교하는 것이다.
형태
interface Comparator<T>{
public int compare(T t1, T t2);
}
위의 Comparable 예시와 비슷하다. t1이 크면 return 1, 작으면 return -1, 같으면 return 0해주면 된다.
예시1)
class Pair implements Comparator<Pair>{
int x;
int y;
@Override
public int compare(Pair p1, Pair p2){
return p1.x - p2.x;
}
}
// main부
ArrayList<Pair> pairList = new ArrayList<>();
MyComparator myComparator = new MyComparator();
Collections.sort(pairList, myComparator); // pairList에 객체들이 있다고 가정
예시2)
class Pair implements Comparator<Pair>{
int x;
int y;
@Override
public int compare(Pair p1, Pair p2){
if(p1.x > p2.x){
return 1;
}
else if(p1.x < p2.x){
return -1;
}
else{
if(p1.y > p2.y){
return 1;
}else if(p1.y < p2.y){
return -1;
}
return 0;
}
}
// main부
ArrayList<Pair> pairList = new ArrayList<>();
MyComparator myComparator = new MyComparator();
Collections.sort(pairList, myComparator); // pairList에 객체들이 있다고 가정
무명클래스로 만든 Comparator
위와 같이 클래스에 일일히 Comparator를 implements하고 compare를 구현하는 것이 아니라,
ArrayList를 한번 정렬하거나 혹은 <정렬 메소드를 만들어놓고 그 정렬 메소드에 원하는 Comparator기준을 적용 시켜놓으면 원하는 각각의 정렬대로 각각의 메소드를 호출하면 되기때문에 편리하지 않을까?>
예시3)
void minTime() {
Collections.sort(nowArr, new Comparator<Schedule>() {
@Override
public int compare(Schedule s1, Schedule s2) {
if (s1.movingTime[0] > s2.movingTime[0]) {
return 1;
} else if (s1.movingTime[0] < s2.movingTime[0]) {
return -1;
} else {
if(s1.movingTime[1] > s2.movingTime[1]) {
return 1;
}else if(s1.movingTime[1] < s2.movingTime[1]) {
return -1;
}
return 0;
}
}
});
// setRowCount는 조회 갱신을 위해 이전목록의 내용을 지우는 것.
tableModel.setRowCount(0);
for (Object m : nowArr)
tableModel.addRow(((UIData) m).getUiTexts());
}
배경:
스케줄 객체 Schedule이 있고, 이 필드에는 movingTime이라는 int배열 필드가 있다. 0번 인덱스에는 '시간'값이, 1번 인덱스에는 '분' 값이 있다.
목표:
minTime이라는 메소드를 실행해서 GUI에 적게걸리는 시간순으로 스케줄을 정렬한다.
무명 class로 Compartor 만들기:
원래대로라면 Collections.sort(nowArr, 만들어놓은 Comparator); 가 되야한다.
하지만 무명 class를 통해 바로 저 자리에 Comparator를 만들 수 있다. (어차피 한번 쓸 Comparator기 때문, 여러번쓰려면 메소드로 호출하면 됨)
그리고 시간 기준으로 오름차순 정렬, 분 기준으로 오름차순 정렬해준다.
추가적인 생각
처음에는 Schedule 클래스에 compareTo나 compare를 구현해놓고 정렬할까 했었는데, 그렇게 하면
여러가지 정렬을 수행하지 못한다. 예를들어 Schedule을 시간우선순위로 정렬 or 가격 우선순위로 정렬 or 남은 좌석 우선순위로 정렬 ... 등 하고 싶을 수 잇는데. Schedule안에 compare를 여러개 구현해서 호출하는 것이 불가능했다.
따라서 메소드를 여러개 만들고 메소드에 따라서 각각의 무명클래스 Comparator를 만들었다.
예를들면 가격을 기준으로 정렬하는 메소드는 아래와 같다.
예시4)
void minPrice() {
Collections.sort(nowArr, new Comparator<Schedule>() {
@Override
public int compare(Schedule s1, Schedule s2) {
if (s1.price > s2.price) {
return 1;
} else if (s1.price < s2.price) {
return -1;
} else {
return 0;
}
}
});
// setRowCount는 조회 갱신을 위해 이전목록의 내용을 지우는 것.
tableModel.setRowCount(0);
for (Object m : nowArr)
tableModel.addRow(((UIData) m).getUiTexts());
}
그럼 가격에 따라 정렬하고 싶으면 minprice()호출, 걸리는 시간에 따라 정렬하고 싶으면 minTime() 메소드를 호출해서 정렬하면 된다.