[코딩 초보의 탐구] 백준 10814번 : 나이순 정렬(자바)과 Comparator
🎧 오늘은 클라우드 서비스 정리를 했습니다. 하면서 들을 음악을 선택했는데 손가락이 닿는대로 눌렀더니 저 앨범이었어요. 그런데 너무나도 탁월한 선택이었던 거 있죠?
그럼 바로 문제를 풀러 갑시다.
1. 문제 파악
✅ 제목을 보자마자 정렬 문제임을 알 수 있습니다. 문제를 읽어보면 list에 담아서 정렬을 하면 되겠구나가 바로 떠올랐어요. 나이순으로 정렬하는 것은 Arrays.sort 메서드를 사용하면 될 것 같았고 실버5 치고는 간단해보였습니다.
✅ 하지만 리스트로 만드는 과정에서 에러를 많이 만나게 됩니다. 찾아보다가 Comparable과 Comparator에 대해 알게되었고, 이를 알아보기 시작했습니다.
✅ Comparable과 Comparator 모두 객체의 정렬을 위한 인터페이스라는 공통점을 가지고 있습니다.
2. Comparable
◾ Comparable은 양수, 음수 혹은 0을 리턴값으로 반환하여 정렬을 합니다. CompareTo라는 메서드를 오버라이딩 해서 객체간 비교를 합니다.
◾ 아래는 Comparable의 예시 코드입니다. 입력한 두 개의 과일 이름의 알파벳순 순서를 if문을 돌면서 파악할 수 있습니다.
public class ComparableExample implements Comparable<ComparableExample> {
private String name;
public ComparableExample(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public int compareTo(ComparableExample other) {
return this.name.compareTo(other.getName());
}
public static void main(String[] args) {
ComparableExample example1 = new ComparableExample("Tomato");
ComparableExample example2 = new ComparableExample("Banana");
int result = example1.compareTo(example2);
if (result < 0) {
System.out.println(example1.getName() + " comes before " + example2.getName());
} else if (result > 0) {
System.out.println(example1.getName() + " comes after " + example2.getName());
} else {
System.out.println(example1.getName() + " is equal to " + example2.getName());
}
}
}
◾ 위 코드를 돌리면 아래와 같은 결과가 도출됩니다.
Tomato comes after Banana
◾ 만약 Tomato를 Apple로 바꾸면 다음과 같은 결과가 도출됩니다.
Apple comes before Banana
3. Comparator
◾ Comparator 인터페이스는 두 객체를 비교하는 정렬 규칙을 정의하여 정렬할 수 있습니다.
◾ compare 메서드를 오버라이딩 해서 사용합니다.
◾ 아래는 Comparator를 사용하여 과일 이름을 이름의 길이에 따라 오름차순으로 정렬하는 코드입니다.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ComparatorExample {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Mango");
fruits.add("Tomato");
fruits.add("Banana");
fruits.add("Pineapple");
fruits.add("Orange");
Comparator<String> lengthComparator = Comparator.comparingInt(String::length);
Collections.sort(fruits, lengthComparator);
System.out.print("Sorted by length : ");
for (String fruit : fruits) {
System.out.print(fruit + " ");
}
}
}
◾ 길이 말고 알파벳순으로 정렬하는 코드는 다음과 같습니다.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ComparatorExample {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Mango");
fruits.add("Tomato");
fruits.add("Banana");
fruits.add("Pineapple");
fruits.add("Orange");
Comparator<String> alphabeticalComparator = Comparator.naturalOrder();
Collections.sort(fruits, alphabeticalComparator);
System.out.print("Sorted by alphabet : ");
for (String fruit : fruits) {
System.out.print(fruit + " ");
}
}
}
정답 제출 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;
// 나이순 정렬 (실버5)
public class p10814 {
int age;
String name;
public p10814(int age, String name) {
this.age = age;
this.name = name;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
p10814[] list= new p10814[N];
for (int i = 0; i < N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
list[i] = new p10814(Integer.parseInt(st.nextToken()), st.nextToken());
}
Arrays.sort(list, new Comparator<p10814>() {
@Override
public int compare(p10814 o1, p10814 o2) {
return o1.age - o2.age;
}
});
for (int i = 0; i < N; i++) {
System.out.println(list[i].age + " " + list[i].name);
}
br.close();
}
}
◾ 제출할 때에는 p10814 부분을 모두 Main으로 바꾸어서 제출하였습니다.
◾ 위에 보여드린 예시코드에서는 compare를 메서드로 오버라이드 해오지 않았었는데, 이 코드에서는 compare를 오버라이드 하였습니다. Integer.compare 메서드를 사용할 수도 있으나, o1.age - o2.age를 리턴해서 메서드를 구현하는 방법을 사용하였습니다.
◾ 위가 Integer.compare 메서드 사용, 아래가 o1.age - o2.age 사용한 코드입니다. 메모리는 전자가 조금 더 적고, 시간은 더 걸리네요. 어떤 방식을 사용하여도 괜찮을 것 같습니다.
🚨 본 포스팅은 개인적인 학습 목적으로 작성되었습니다.
정확하고 날카로운 풀이를 원하시는 분들은 고수분들의 포스팅을 보시기를 권장드립니다.