Java에서 객체의 정렬을 구현할 때 주로 사용하는 두 가지 인터페이스인 Comparable과 Comparator에 대해 알아보겠다. 이 두 인터페이스는 컬렉션의 정렬 기준을 정의하는 데 중요한 역할을 하며, 각각의 특성과 사용법을 이해하는 것이 필요하다.
1. Comparable 인터페이스
Comparable 인터페이스는 객체 자체에 기본 정렬 순서를 정의할 때 사용된다. 이 인터페이스를 구현하면, 해당 객체는 기본적인 정렬 기준을 가지게 되며, Collections.sort() 또는 Arrays.sort() 메서드를 사용할 때 자동으로 이 기준을 따르게 된다.
[주요 메서드]
- int compareTo(T o) : 현재 객체와 매개변수로 전달된 객체를 비교하여 순서를 결정하는 메서드이다. 이 메서드는 세 가지 값을 반환할 수 있다.
- -(음수값): 현재 객체가 매개변수 객체보다 작음을 의미
- 0: 현재 객체와 매개변수 객체가 같음을 의미
- +(양수값): 현재 객체가 매개변수 객체보다 큼을 의미
package collection.compare;
public class MyUser implements Comparable<MyUser> {
private String id;
private int age;
public MyUser(String id, int age) {
this.id = id;
this.age = age;
}
public String getId() {
return id;
}
public int getAge() {
return age;
}
@Override // 정렬의 기준을 age로 정했다 (나이 오름차순)
public int compareTo(MyUser o) {
return (this.age < o.age) ? -1 : ((this.age == o.age) ? 0 : 1);
}
@Override
public String toString() {
return "MyUser{" +
"id='" + id + '\'' +
", age=" + age +
'}';
}
}
2. Comparator 인터페이스
Comparator 인터페이스는 "객체"의 정렬 기준을 외부에서 정의할 때 사용된다. 이 인터페이스를 구현하면, 동일한 객체라도 다양한 정렬 기준을 가질 수 있으며, 필요에 따라 다른 기준으로 정렬할 수 있다.
[주요 메서드]
- int compare(T o1, T o2) : 두 객체를 비교하여 순서를 결정하는 메서드이다. 이 메서드는 Comparable의 compareTo 메서드와 유사하게 음수값, 0, 양수값을 반환한다.
- boolean equals(Object obj) : (선택적) 두 Comparator가 동일한지 비교하는 메서드이다.
package collection.compare;
import java.util.Comparator;
public class IdComparator implements Comparator<MyUser> {
@Override
public int compare(MyUser o1, MyUser o2) {
return o1.getId().compareTo(o2.getId());
}
}
(테스트 메인 코드)
package collection.compare;
import java.util.Arrays;
public class SortMain3 {
public static void main(String[] args) {
MyUser myUser1 = new MyUser("a", 30);
MyUser myUser2 = new MyUser("b", 20);
MyUser myUser3 = new MyUser("c", 10);
MyUser[] array = {myUser1, myUser2, myUser3};
System.out.println("기본 데이터");
System.out.println(Arrays.toString(array));
System.out.println();
System.out.println("Comparable 기본 정렬");
Arrays.sort(array);
System.out.println(Arrays.toString(array));
// 추가 (id 기준 정렬)
System.out.println();
System.out.println("IdComparator 정렬");
Arrays.sort(array, new IdComparator());
System.out.println(Arrays.toString(array));
System.out.println("IdComparator.reversed() 정렬");
Arrays.sort(array, new IdComparator().reversed());
System.out.println(Arrays.toString(array));
}
}
+ Collection 자료구조에도 적용할 수 있다
(List 테스트 코드)
package collection.compare;
import java.util.ArrayList;
import java.util.List;
public class SortMain4 {
public static void main(String[] args) {
MyUser myUser1 = new MyUser("a", 30);
MyUser myUser2 = new MyUser("b", 20);
MyUser myUser3 = new MyUser("c", 10);
List<MyUser> list = new ArrayList<>();
list.add(myUser1);
list.add(myUser2);
list.add(myUser3);
System.out.println("기본 데이터");
System.out.println(list + "\n");
System.out.println("Comparable 기본 정렬");
list.sort(null); // 객체 스스로의 정렬 메서드를 갖고 있는 list.sort()를 추천
// Collections.sort(list); - 비추천
System.out.println(list + "\n");
System.out.println("IdComparator 정렬");
list.sort(new IdComparator()); // 객체 스스로의 정렬 메서드를 갖고 있는 list.sort()를 추천
// Collections.sort(list) - 비추천
System.out.println(list);
System.out.println("IdComparator reversed 정렬");
list.sort(new IdComparator().reversed()); // 객체 스스로의 정렬 메서드를 갖고 있는 list.sort()를 추천
// Collections.sort(list) - 비추천
System.out.println(list);
}
}
(TreeSet 테스트 코드)
package collection.compare;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
public class SortMain5 {
public static void main(String[] args) {
MyUser myUser1 = new MyUser("a", 30);
MyUser myUser2 = new MyUser("b", 20);
MyUser myUser3 = new MyUser("c", 10);
TreeSet<MyUser> treeSet1 = new TreeSet<>();
treeSet1.add(myUser1);
treeSet1.add(myUser2);
treeSet1.add(myUser3);
System.out.println("Comparable 기본 정렬");
System.out.println(treeSet1);
System.out.println();
TreeSet<MyUser> treeSet2 = new TreeSet<>(new IdComparator());
treeSet2.add(myUser1);
treeSet2.add(myUser2);
treeSet2.add(myUser3);
System.out.println("IdComparator 정렬");
System.out.println(treeSet2);
TreeSet<MyUser> treeSet3 = new TreeSet<>(new IdComparator().reversed());
treeSet3.add(myUser1);
treeSet3.add(myUser2);
treeSet3.add(myUser3);
System.out.println("IdComparator reversed 정렬");
System.out.println(treeSet3);
}
}
[Comparable vs Comparator]
※ 람다 표현식을 사용한 Comparator
Java 8 이후, Comparator 인터페이스는 람다 표현식을 사용하여 더 간결하게 구현할 수가 있다.
package collection.compare;
import java.util.Arrays;
public class SortMain3 {
public static void main(String[] args) {
MyUser myUser1 = new MyUser("a", 30);
MyUser myUser2 = new MyUser("b", 20);
MyUser myUser3 = new MyUser("c", 10);
MyUser[] array = {myUser1, myUser2, myUser3};
System.out.println("기본 데이터");
System.out.println(Arrays.toString(array));
System.out.println();
System.out.println("Comparable 기본 정렬");
Arrays.sort(array);
System.out.println(Arrays.toString(array));
// 추가 (id 기준 정렬)
System.out.println();
System.out.println("IdComparator 정렬 (람다 표현식 사용)");
Arrays.sort(array, (user1, user2) -> user1.getId().compareTo(user2.getId()));
System.out.println(Arrays.toString(array));
System.out.println();
System.out.println("IdComparator.reversed() 정렬 (람다 표현식 사용)");
Arrays.sort(array, (user1, user2) -> user2.getId().compareTo(user1.getId()));
System.out.println(Arrays.toString(array));
}
}
'Language > Java' 카테고리의 다른 글
[Java] 컬렉션 프레임워크 선택 매뉴얼 (0) | 2024.10.27 |
---|---|
[Java API] java.util.Collections 메서드 (0) | 2024.10.27 |
[Java API] Iterable, Iterator 인터페이스 (1) | 2024.10.25 |
[Java API] Queue, Deque 인터페이스(ArrayDeque, LinkedList) (0) | 2024.09.22 |
[Java API] Stack 클래스(사용하면 안된다) (1) | 2024.09.21 |