아래의 내용은 java_grammer 레파지토리 C05AnonymousLambda 디렉터리에 저장되어있는 내용을 정리함
자바에서는 비교를 위한 인터페이스로 대표적으로 두 가지가 있음.
| 인터페이스 | 메서드 | 특징 |
|---|---|---|
| Comparator | int compare(T o1, T o2) | 외부 정렬 기준. 별도 비교 객체를 생성해서 사용함. |
| Comparable | int compareTo(T o) | 내부 정렬 기준. 비교 대상 클래스 자체에 구현함. |
List<Integer> myList = new ArrayList<>();
myList.add(10); myList.add(20); myList.add(30);
// 기본 오름차순 정렬
myList.sort(Comparator.naturalOrder());
// 람다식으로 직접 구현한 오름차순 정렬
myList.sort((o1, o2) -> o1 - o2);
(o1, o2) -> o1 - o2 → **o1이 먼저** = **오름차순**
(o1, o2) -> o2 - o1 → **o2가 먼저** = **내림차순**
compare 메서드의 반환값 규칙:
o1이 o2보다 앞에 배치 o2가 o1보다 앞에 배치 List<String> myList2 = new ArrayList<>();
myList2.add("java"); myList2.add("python"); myList2.add("c++");
// 기본 내림차순 정렬 (알파벳순)
Collections.sort(myList2, Comparator.reverseOrder());
System.out.println("기본 내림차순 정렬 : " + myList2);
// [python, java, c++]
// 알파벳순 내림차순
Collections.sort(myList2, (o1, o2) -> o2.compareTo(o1));
System.out.println("알파벳순 내림차순 정렬 : " + myList2);
// 문자열 길이 기준 오름차순
Collections.sort(myList2, (o1, o2) -> o1.length() - o2.length());
System.out.println("문자길이순 오름차순 정렬 : " + myList2);
// [c++, java, python]
문자열 길이로 정렬하되, 길이가 같으면 알파벳순으로 정렬하는 예시임.
myList2.add("HTML"); // 길이 4
Collections.sort(myList2, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
if (o1.length() == o2.length()) {
return o1.compareTo(o2); // 길이 같으면 알파벳순
} else {
return o1.length() - o2.length(); // 길이 다르면 길이순
}
}
});
System.out.println("문자길이순 & 알파벳순 정렬 오름차순 : " + myList2);
// [c++, java, HTML, python]
람다식으로 간결하게 표현하면:
Collections.sort(myList2, (o1, o2) -> {
if (o1.length() == o2.length()) return o1.compareTo(o2);
return o1.length() - o2.length();
});
요구사항: 리스트 안의 배열에 1번째 index를 기준으로 오름차순 정렬
[{4,5},{1,2},{5,0},{3,1}] → [{5,0},{3,1},{1,2},{4,5}]
List<int[]> arrList = new ArrayList<>();
arrList.add(new int[]{4,5});
arrList.add(new int[]{1,2});
arrList.add(new int[]{5,0});
arrList.add(new int[]{3,1});
Collections.sort(arrList, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[1] - o2[1]; // 1번째 인덱스(5,2,0,1) 기준 정렬
}
});
for (int[] arr : arrList) {
System.out.println(Arrays.toString(arr));
}
// [5, 0], [3, 1], [1, 2], [4, 5]
PriorityQueue, TreeSet, TreeMap 등에서도 동일하게 Comparator 사용함.
// PriorityQueue: 문자열 길이순 정렬
Queue<String> pq = new PriorityQueue<>((o1, o2) -> o1.length()-o2.length());
// TreeSet: 문자열 길이순 정렬 (중복 제거)
Set<String> treeSet = new TreeSet<>((o1, o2) -> o1.length() - o2.length());
백준 - 최대값 힙 문제
PriorityQueue<Integer> maxHeap = new PriorityQueue<>((o1, o2) -> o2 - o1);
TODO 백준 문제:
Student 클래스 요구사항: name, age 변수 / 생성자 / getter / toString
class Student implements Comparable<Student> {
private String name;
private int age;
public Student(String name, int age) { this.name = name; this.age = age; }
public String getName() { return name; }
public int getAge() { return age; }
@Override
public String toString() {
return "{" + "name='" + name + '\'' + ", age='" + age + '\'' + '}';
}
// Comparable: this와 o 비교
@Override
public int compareTo(Student o) {
return this.getName().compareTo(o.getName()); // 이름순 오름차순
}
}
List<Student> students = new ArrayList<>();
students.add(new Student("lee", 20));
students.add(new Student("kim", 45));
students.add(new Student("park", 13));
students.add(new Student("hong", 20));
// 방법(1) Comparator 익명객체: 나이순
/*
Collections.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge() - o2.getAge(); // 13,20,20,45
}
});
*/
// 방법(2) Comparable 구현: 이름순 (클래스 자체에 compareTo 구현)
Collections.sort(students); // 자동으로 Student.compareTo 호출
System.out.println(students);
// [{name='hong', age='20'}, {name='kim', age='45'}, {name='lee', age='20'}, {name='park', age='13'}]
Comparable 단점: 객체 자체에 정렬 기준 고정. 유연성 떨어짐.
| 메서드 | 설명 | Comparator 필요 여부 |
|---|---|---|
list.sort(comparator) | List 정렬 | 필요 |
Collections.sort(list) | List 정렬 (기본/Comparable) | 불필요 |
Collections.sort(list, comparator) | List 정렬 (커스텀) | 필요 |
new PriorityQueue<>(comparator) | 우선순위큐 | 필요 |
new TreeSet<>(comparator) | 정렬 집합 | 필요 |
(o1, o2) -> o1 - o2 if-else나 다중 조건으로 구현함. compareTo 구현. 단점: 유연성 부족. Stream 연계: list.stream().sorted((o1,o2)->o1.age-o2.age)