백준 문제를 풀이하면서 절댓값 함수 Math.abs()를 사용해야 하는 것은 알고 있으나 어떻게 우선순위 큐에 활용을 해야할지 몰라 해설을 보았는데,
오버라이딩과 Comparator 인터페이스를 사용하는 것을 보고 정리를 해보려고 합니다.
ex) 클래스 내의 객체를 비교할 때
public class Test { public static void main(String[] args) { Student a = new Student(17, 2); // 17살 2반 Student b = new Student(18, 1); // 18살 1반 /* 어떻게 비교..? if(a > b) ..? */ } } class Student { int age; // 나이 int classNumber; // 학급 Student(int age, int classNumber) { this.age = age; this.classNumber = classNumber; } }
- 두 객체 a 학생과 b 학생이 있을 때 무엇을 기준으로 비교할지 판단이 불가능하다.
따라서, 이러한 문제점 해결을 위해 Comparable 또는 Comparator을 사용한다- 이 두 인터페이스에도 차이가 존재한다
- Comparable은 자기 자신과 매개변수 객체를 비교
- Comparator는 두 매개변수 객체를 비교
- Comparabledms lang 패키지에 속해있어 import를 해줄 필요가 없으나, Comparator는 util 패키지에 있어 선언을 해주어야 한다.
class Student implements Comparable<Student> { int age; // 나이 int classNumber; // 학급 Student(int age, int classNumber) { this.age = age; this.classNumber = classNumber; } @Override public int compareTo(Student o) { // 자기자신의 age가 o의 age보다 크다면 양수 if(this.age > o.age) { return 1; } // 자기 자신의 age와 o의 age가 같다면 0 else if(this.age == o.age) { return 0; } // 자기 자신의 age가 o의 age보다 작다면 음수 else { return -1; } } }
- Student 클래스에 Comparable을 implements한다
- Comparable<> 사이에 들어갈 타입은 Student 객체와 또 다른 Student 객체를 비교해야 하므로 <> 타입 또한 Student가 되어야 한다
- 조건문을 통해 대소비교를 하고 그에 따라 1, 0, -1을 반환하는 방식이 정석적인 방법이지만 양수, 0, 음수로 표현하여도 무관하다
public int compareTo(Student o) { return this.age - o.age; }
import java.util.Comparator; // import 필요 class Student implements Comparator<Student> { int age; // 나이 int classNumber; // 학급 Student(int age, int classNumber) { this.age = age; this.classNumber = classNumber; } @Override public int compare(Student o1, Student o2) { // o1의 학급이 o2의 학급보다 크다면 양수 if(o1.classNumber > o2.classNumber) { return 1; } // o1의 학급이 o2의 학급과 같다면 0 else if(o1.classNumber == o2.classNumber) { return 0; } // o1의 학급이 o2의 학급보다 작다면 음수 else { return -1; } } }
- Comparable의 compareTO()와는 다르게 자기 자신이 아닌 다른 두 객체를 비교하는 것을 확인할 수 있다
- import java.util.Comparator; 선언해야 한다
- compare 함수도 위와 마찬가지로 간략하게 할 수 있다
public int compare(Student o1, Student o2) { return o1.classNumber - o2.classNumber; }
- 예시 코드
import java.util.Comparator; public class Test { public static void main(String[] args) { Student a = new Student(17, 2); // 17살 2반 Student b = new Student(18, 1); // 18살 1반 Student c = new Student(15, 3); // 15살 3반 // a객체와는 상관 없이 b와 c객체를 비교한다. int isBig = a.compare(b, c); if(isBig > 0) { System.out.println("b객체가 c객체보다 큽니다."); } else if(isBig == 0) { System.out.println("두 객체의 크기가 같습니다."); } else { System.out.println("b객체가 c객체보다 작습니다."); } } } class Student implements Comparator<Student> { int age; // 나이 int classNumber; // 학급 Student(int age, int classNumber) { this.age = age; this.classNumber = classNumber; } @Override public int compare(Student o1, Student o2) { return o1.classNumber - o2.classNumber; } }
- Compaartor을 구현하는 두 번째 방법(추천)
// 학급 대소 비교 익명 객체 public static Comparator<Student> comp = new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { return o1.classNumber - o2.classNumber; } }; // 나이 대소 비교 익명 객체 public static Comparator<Student> comp2 = new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { return o1.age - o2.age; } }; } class Student { int age; // 나이 int classNumber; // 학급 Student(int age, int classNumber) { this.age = age; this.classNumber = classNumber; } }
- 익명객체를 이용한 방법으로 외부에서 Comparator을 구현하였기 때문에, Student 클래스 내부에서 구현해줄 필요가 없어짐
- 음수가 나오면 두 원소의 위치를 바꾸지 않는다
- 양수가 나오면 두 원소의 위치를 교환 한다
- 같으면 두 원소의 위치는 그대로
ex)
import java.util.Arrays; import java.util.Comparator; public class Test { public static void main(String[] args) { MyInteger[] arr = new MyInteger[10]; // 객체 배열 초기화 (랜덤 값으로) for(int i = 0; i < 10; i++) { arr[i] = new MyInteger((int)(Math.random() * 100)); } // 정렬 이전 System.out.print("정렬 전 : "); for(int i = 0; i < 10; i++) { System.out.print(arr[i].value + " "); } System.out.println(); Arrays.sort(arr, comp); // MyInteger에 대한 Comparator을 구현한 익명객체를 넘겨줌 // 정렬 이후 System.out.print("정렬 후 : "); for(int i = 0; i < 10; i++) { System.out.print(arr[i].value + " "); } System.out.println(); } static Comparator<MyInteger> comp = new Comparator<MyInteger>() { @Override public int compare(MyInteger o1, MyInteger o2) { return o1.value - o2.value; } }; } class MyInteger { int value; public MyInteger(int value) { this.value = value; } }