[Java] 생성한 객체 배열 정렬하기(Comparator)
프로젝트를 진행하다보면 개발 중에 생성한 객체로 이루어진 배열을 원하는 값에 따라 정렬이 필요할 때가 있다.
이러한 경우에 아래의 방법을 통해서 정렬이 가능하다.
아래와 같은 객체를 생성해본다.
public class blogVO {
private String name = null;
private String gender = null;
private String age = null;
private String id = null;
public blogVO(String name, String gender, String age, String id) {
super();
this.name = name;
this.gender = gender;
this.age = age;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
....
}
해당 객체를 배열로 생성하고, 정렬을 시도한다.
기본적으로 자주 사용하는 Arrays.sort()를 사용한다.
sorting(정렬) 의 가장 간단한 방법은 Collections.sort 와 Arrays.sort 가 있다.
두 메소드 전부 O(n log n)의 속도를 보장한다.
public class blogTest {
public static void main(String[] args) {
blogVO[] blogVO = new blogVO[] {
new blogVO("hwang", "M", "28", "test@naver.com"),
new blogVO("kim", "W", "20", "blog@naver.com"),
new blogVO("lee", "W", "30", "write@naver.com"),
new blogVO("park", "M", "35", "sample@naver.com")
};
// 에러 발생
Arrays.sort(blogVO);
}
}
그러나, 위의 코드는 에러를 발생시킨다.
이유는 sort 의 인자가 우리가 만든 custom object(객체) 가 될 수 없어서이다.(해당 객체에서 어떤 변수를 키로써 정렬할지를 지정해야 한다.)
기본적으로 배열은 자연적인 순서로 Natural Order 로 정렬된다.
아래는 Java Doc에서 제공하는 정렬에 관한 글이다.
If the List consists of String elements, it will be sorted into alphabetical order. If it consists of Date elements, it will be sorted into chronological order. How does this happen? String and Date both implement the Comparable interface. Comparable implementations provide a natural ordering for a class, which allows objects of that class to be sorted automatically. The following table summarizes some of the more important Java platform classes that implement Comparable.
-- Oracle Java Doc
간단하게 번역해서 이해해보자면, "리스트가 문자열이면 알파벳 순이며, 시간이면 시간, 숫자면 숫자순으로 정렬된다. 이는 자연스러우며, 자바에서 제공하는 Comparable 인터페이스에는 이 자연스러운 순서대로 정렬이 되도록 한다."
해당 인터페이스(Comparable)를 통해 원하는 변수의 순서대로 배열이 정렬되게 해보려한다.
case 1. comparator 를 사용한 정렬
위의 정렬을 하는 코드를 아래와 같이 수정한다.
import java.util.Arrays;
import java.util.Comparator;
public class blogTest {
public static void main(String[] args) {
blogVO[] blogVOArr = new blogVO[] {
new blogVO("hwang", "M", "28", "test@naver.com"),
new blogVO("kim", "W", "20", "blog@naver.com"),
new blogVO("lee", "W", "30", "write@naver.com"),
new blogVO("park", "M", "35", "sample@naver.com")
};
System.out.println("===== 정렬전 =====");
for (blogVO test : blogVOArr) {
System.out.println(test.toString());
}
// 기존의 Arrays.sort(blogVOArr)를 아래와 같이 수정.
// age 형이 현재 String이므로 int형으로 변환하여 정렬한다.
Arrays.sort(blogVOArr, new Comparator<blogVO>() {
@Override
public int compare(blogVO o1, blogVO o2) {
return Integer.compare(Integer.parseInt(o1.getAge()), Integer.parseInt(o2.getAge()));
}
});
System.out.println("===== 정렬후 =====");
for (blogVO test : blogVOArr) {
System.out.println(test.toString());
}
}
}
Comparator 의 인터페이스에 두개의 파라미터로 이너클래스 객체를 전달하게 된다. 해당 객체는 비교할 두 객체를 인자로 받아 각각의 값을 꺼내와 Integer 클래스에 정의된 compare 메소드로 두 값을 비교한다.
o1.getAge() == o2.getAge() 일 경우 0 리턴
o1.getAge() < o2.getAge() 일 경우 음수 리턴
o1.getAge() > o2.getAge() 일 경우 양수 리턴
위의 비교를 통해서 객체를 재정렬한다.
===== 정렬전 =====
blogVO [name=hwang, gender=M, age=28, id=test@naver.com]
blogVO [name=kim, gender=W, age=20, id=blog@naver.com]
blogVO [name=lee, gender=W, age=30, id=write@naver.com]
blogVO [name=park, gender=M, age=35, id=sample@naver.com]
===== 정렬후 =====
blogVO [name=kim, gender=W, age=20, id=blog@naver.com]
blogVO [name=hwang, gender=M, age=28, id=test@naver.com]
blogVO [name=lee, gender=W, age=30, id=write@naver.com]
blogVO [name=park, gender=M, age=35, id=sample@naver.com]
case 2. Lamda 를 사용한 comparator정렬
같은 comparator를 사용하지만 Lamda를 사용하여 위의 Line을 줄이고 가시성을 높일 수 있다.
// Lamda 사용
Arrays.sort(blogVOArr, (o1, o2) -> {
return Integer.compare(Integer.parseInt(o1.getAge()), Integer.parseInt(o2.getAge()));
});
// Arrays.sort(blogVOArr, new Comparator<blogVO>() {
//
// @Override
// public int compare(blogVO o1, blogVO o2) {
// return Integer.compare(Integer.parseInt(o1.getAge()), Integer.parseInt(o2.getAge()));
// }
//
// });
참고