학생 클래스를 만들 때, 나이를 기준으로 비교할 것인지 학급을 기준으로 비교할 것인지 설정하는 것
public interface Comparable {
int compareTo(Object o);
//객체 자신(this)와 o를 비교한다.
}
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 142352;
}
// 자기 자신의 age와 o의 age가 같다면 0
else if(this.age == o.age) {
return 0;
}
// 자기 자신의 age가 o의 age보다 작다면 음수
else {
return -1324;
}
}
}
양수 음수 값은 관계가 없기 때문에, 그냥 차이를 반환해도 된다.
@Override
public int compareTo(Student o) {
/*
* 만약 자신의 age가 o의 age보다 크다면 양수가 반환 될 것이고,
* 같다면 0을, 작다면 음수를 반환할 것이다.
*/
return this.age - o.age;
}
public interface Comparator {
int compare(Object o1, Object o2);
boolean equals(Object obj);
}
import java.util.Comparator; // import 필요
// Comparator<Student> 를 implement 한다.
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;
}
}
}
Comparator을 통해 , compare 메소드를 사용하려면, compare 메소드를 활용하기위한 객체가 필요하다.
하지만 compare을 사용하기 위해선 쓸모가 없음에도 새로운 변수를 만들거나, 일관성이 떨어지는 코드를 작성해야한다는 문제가 발생한다. 그럴 땐 익명 객체를 사용하기로 한다.
Comparator의 비교 기능만 따로 사용하고싶다.
class name = new class() { ~~~ }; 로 표현한다.
public class Test{
private String st = "test";
public String getSt() {
return this.st;
}
}
public static void main(String[] args) {
// 일반적인 사용
Test ABC = new Test();
System.out.println(ABC.getSt());
// 익명 객체를 사용
Test DEF = new Test() {
private String st = "유후";
@Override
public String getSt(){
return this.st;
}
}
System.out.println(DEF.getSt());
// 유후가 출력된다.
}
그렇다면, Comparator의 기능만 사용하고 싶을 때, Comparator는 interface이고, 이를 구현하는 익명객체를 생성하면 된다.
학급을 기준으로 대소비교를 하거나, 나이를 기준으로 대소비교를 할 수 있다.
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
// 익명 객체 구현방법 1
Comparator<Student> comp1 = new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.classNumber - o2.classNumber;
}
};
}
// 익명 객체 구현 2
public static Comparator<Student> comp2 = new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.classNumber - o2.classNumber;
}
};
}
// 외부에서 익명 객체로 Comparator가 생성되기 때문에 클래스에서 Comparator을 구현 할 필요가 없어진다.
class Student {
int age; // 나이
int classNumber; // 학급
Student(int age, int classNumber) {
this.age = age;
this.classNumber = classNumber;
}
}
다음과 같은 클래스가 있다.
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));
}
}
}
class MyInteger {
int value;
public MyInteger(int value) {
this.value = value;
}
}
MyInteger 클래스의 비교기준은 없다.
class MyInteger implements Comparable<MyInteger> {
int value;
public MyInteger(int value) {
this.value = value;
}
// 자기 자신의 value을 기준으로 파라미터 값과의 차이를 반환한다.
@Override
public int compareTo(MyInteger o) {
return this.value - o.value;
}
}
import java.util.Arrays;
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);
// 정렬 이후
System.out.print("정렬 후 : ");
for(int i = 0; i < 10; i++) {
System.out.print(arr[i].value + " ");
}
System.out.println();
}
}
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;
}
}
class Main {
public static void main(String[] args){
Integer[] arr = {30,50,10,40,20};
//일반 디폴트 정렬
// Integer가 가지고 있는 기본 정렬 compareTo로 정렬함
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
// 만들어서 구현한 정렬 기준으로
Arrays.sort(arr, new XXXX());
Arrays.sort(arr, new XXXX());
/// XXXX라는 정렬 기준을 사용한다.
System.out.println(Arrays.toString(arr));
}
}
class XXXX implements Comparator {
}
class XXXX implements Comparator {
public int compare(Object o1, Object o2 ){
Integer A = (Integer) o1;
Integer B = (Integer) o2;
return A.compareTo(B) * -1;
return B - A; // 이렇게 두가지 방식이 가능하다.
}
}
반대로 값을 리턴해주면 된다.
// Comparable
public int compareTo(MyClass o) {
return -(this.value - o.value);
}
// Comparator
public int compare(Myclass o1, MyClass o2) {
return -(o1.value - o2.value);
}
또는
// Comparable
public int compareTo(MyClass o) {
return o.value - this.value; // == -(this.value - o.value);
}
// Comparator
public int compare(Myclass o1, MyClass o2) {
return o2.value - o1.value; // == -(o1.value - o2.value);
}