코딩을 하다보면 컬렉션에 들어있는 객체를 정렬해야 할때가 있다. 이때 객체의 정렬 기준을 "Comparable"이나 "Comparator"를 이용해서 명시해줄 수 있다.
1. Comparable
Comparable 인터페이스는 정렬 수행 시 기본적으로 적용되는 정렬 기준이 되는 메소드를 정의하는 인터페이스이다.
Java에서 제공되는 정렬이 가능한 클래스들은 모두 Comparable 인터페이스를 구현한다. 정렬 시에 이에 맞게 정렬이 수행된다.
// Integer class
public final class Integer extends Number implements Comparable<Integer> { ... }
// String class
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { ... }
(ex) Integer, Double 클래스 : 오름차순 정렬
(ex) String 클래스 : 사전순 정렬
정렬할 객체에 Comparable interface를 구현하고, compareTo() 메소드를 오버라이드하여 구현한다.
음수 또는 0이면 객체의 자리가 그대로 유지되고, 양수인 경우에는 두 객체의 자리가 바뀐다.
compareTo() 메소드는 아래와 같이 작성한다.
- 현재 객체의 값 < 파라미터로 넘어온 객체의 값 : -1 리턴
- 현재 객체의 값 == 파라미터로 넘어온 객체의 값 : 0리턴
- 현재 객체의 값 > 파라미터로 넘어온 객체의 값 : 1 리턴
Point 클래스를 만들어서 오름차순과 내림 차순으로 정렬해 보겠다.
class Point implements Comparable<Point> {
private int x;
private int y;
public Point(int x, int y){
this.x = x;
this.y = y;
}
@Override
public String toString(){
return this.x + "," + this.y;
}
@Override
public int compareTo(Point p) {
if(this.x > p.x) {
return 1;
} else if(this.x == p.x) {
return 0;
} else{
return -1;
}
}
}
compareTo()를 구현했으니까 이제 main 클래스를 작성해보겠다.
public class Main {
public static void main(String[] args) throws Exception{
List<Point> pointList = new ArrayList<>();
pointList.add(new Point(3, 7));
pointList.add(new Point(1, 5));
pointList.add(new Point(2, 4));
Collections.sort(pointList);
for(Point p : pointList){
System.out.println(p.toString());
}
}
}
출력결과는 오름차순으로 나오는 것을 확인할 수 있다.
1, 5
2, 4
3, 7
내림 차순으로 정렬하려면 파라미터로 넘어온 값이 더 크면 그 때 1을 반환해주면 된다.
class Point implements Comparable<Point> {
private int x;
private int y;
public Point(int x, int y){
this.x = x;
this.y = y;
}
@Override
public String toString(){
return this.x + "," + this.y;
}
@Override
public int compareTo(Point p) {
if(this.x < p.x) {
return 1;
} else if(this.x == p.x) {
return 0;
} else{
return -1;
}
}
}
메인 클래스는 동일하게 유지한다.
public class Main {
public static void main(String[] args) throws Exception{
List<Point> pointList = new ArrayList<>();
pointList.add(new Point(3, 7));
pointList.add(new Point(1, 5));
pointList.add(new Point(2, 4));
Collections.sort(pointList);
for(Point p : pointList){
System.out.println(p.toString());
}
}
}
실행 결과 x값이 큰 순으로 내림차순으로 정렬되는 것을 확인할 수 있다.
#실행 결과
3,7
2,4
1,5
2. Comparator
Comparator 인터페이스를 직접 구현할 수 없는 경우나, 새로운 정렬 기준을 적용하고 싶다면 Comparator 인터페이스를 사용하면 된다. Arrays.sort()나 Collection.sort()의 두번째 파라미터로 넘기면 구현한 기준으로 객체를 정렬할 수 있다.
아래와 같이 Comparable 인터페이스를 implements 했던 코드를 수정한다.
class Point{
private int x;
private int y;
public Point(int x, int y){
this.x = x;
this.y = y;
}
public int getX(){
return this.x;
}
public int getY(){
return this.y;
}
@Override
public String toString(){
return this.x + "," + this.y;
}
}
이제 메인클래스에서 Comparator를 직접 넣어준다. 앞에 수가 더 클경우 1을 반환하므로 오름차순으로 정렬 된다.
public class Main {
public static void main(String[] args) throws Exception{
List<Point> pointList = new ArrayList<>();
pointList.add(new Point(3, 7));
pointList.add(new Point(1, 5));
pointList.add(new Point(2, 4));
Collections.sort(pointList, new Comparator<Point>() {
@Override
public int compare(Point o1, Point o2) {
if(o1.getX() > o2.getX()){
return 1;
} else if(o1.getX() == o2.getX()){
return 0;
} else{
return -1;
}
}
});
for(Point p : pointList){
System.out.println(p.toString());
}
}
}
다음은 실행 결과이다.
1,5
2,4
3,7
내림 차순으로 정렬하려면 뒤에가 더 클 경우 1을 반환하면 된다.
public class Main {
public static void main(String[] args) throws Exception{
List<Point> pointList = new ArrayList<>();
pointList.add(new Point(3, 7));
pointList.add(new Point(1, 5));
pointList.add(new Point(2, 4));
Collections.sort(pointList, new Comparator<Point>() {
@Override
public int compare(Point o1, Point o2) {
if(o1.getX() < o2.getX()){
return 1;
} else if(o1.getX() == o2.getX()){
return 0;
} else{
return -1;
}
}
});
for(Point p : pointList){
System.out.println(p.toString());
}
}
}
실행 결과
3,7
2,4
1,5
3. 람다를 이용한 정렬
람다를 사용하면 코드를 더 간결하게 짤 수 있다.
public class Main {
public static void main(String[] args) throws Exception{
List<Point> pointList = new ArrayList<>();
pointList.add(new Point(3, 7));
pointList.add(new Point(1, 5));
pointList.add(new Point(2, 4));
//오름차순 정렬
Collections.sort(pointList, (a, b) -> a.getX() - b.getX());
for(Point p : pointList){
System.out.println(p.toString());
}
//내림차순 정렬
Collections.sort(pointList, (a, b) -> b.getX() - a.getX());
for(Point p : pointList){
System.out.println(p.toString());
}
}
}
실행 결과 오름차순으로 한번 출력해주고, 내림차순으로 한번 출력해주는 것을 볼 수 있다.
1,5
2,4
3,7
3,7
2,4
1,5
오름차순 정렬시에 뒤에 나온게 앞에 나온거보다 크다면 내림차순이기 때문에 2개의 자리를 바꿔줘야한다. 그래서 그 경우에 양수를 반환한다. 내림차순으로 정렬하려면 앞에가 더 커야하므로, 뒤에가 더 클 경우 양수를 반환한다. 이것만 기억하면 헷갈리지 않고 정렬 기준을 만들 수 있다.
'Java' 카테고리의 다른 글
[Java] Garbage Collector (0) | 2021.01.17 |
---|---|
JVM Stack & Heap (0) | 2021.01.17 |
[Java] 자바 Collection (0) | 2020.06.14 |
[Java] 객체 값 복사 - clone() 예제 (0) | 2020.05.31 |
[Java-source quality] Redundant Modifier (0) | 2020.05.29 |