예를 들어
import java.util.Date;
public class person {
Date birthDt;
int age;
String name;
String address_country;
String address_city;
String address_detail;
String hobby;
char gender;
double weight;
double height;
public Date getBirthDt() {
return birthDt;
}
public void setBirthDt(Date birthDt) {
this.birthDt = birthDt;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress_country() {
return address_country;
}
public void setAddress_country(String address_country) {
this.address_country = address_country;
}
public String getAddress_city() {
return address_city;
}
public void setAddress_city(String address_city) {
this.address_city = address_city;
}
public String getAddress_detail() {
return address_detail;
}
public void setAddress_detail(String address_detail) {
this.address_detail = address_detail;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
}
person class가 있고,
import java.util.Comparator;
public class PeopleCompareUtil implements Comparator<Object> {
/**
* Compares its two arguments for order. Returns a negative integer,
* zero, or a positive integer as the first argument is less than, equal
* to, or greater than the second.<p>
* <p>
* The implementor must ensure that {@link Integer#signum
* signum}{@code (compare(x, y)) == -signum(compare(y, x))} for
* all {@code x} and {@code y}. (This implies that {@code
* compare(x, y)} must throw an exception if and only if {@code
* compare(y, x)} throws an exception.)<p>
* <p>
* The implementor must also ensure that the relation is transitive:
* {@code ((compare(x, y)>0) && (compare(y, z)>0))} implies
* {@code compare(x, z)>0}.<p>
* <p>
* Finally, the implementor must ensure that {@code compare(x,
* y)==0} implies that {@code signum(compare(x,
* z))==signum(compare(y, z))} for all {@code z}.
*
* @param o1 the first object to be compared.
* @param o2 the second object to be compared.
* @return a negative integer, zero, or a positive integer as the
* first argument is less than, equal to, or greater than the
* second.
* @throws NullPointerException if an argument is null and this
* comparator does not permit null arguments
* @throws ClassCastException if the arguments' types prevent them from
* being compared by this comparator.
* @apiNote It is generally the case, but <i>not</i> strictly required that
* {@code (compare(x, y)==0) == (x.equals(y))}. Generally speaking,
* any comparator that violates this condition should clearly indicate
* this fact. The recommended language is "Note: this comparator
* imposes orderings that are inconsistent with equals."
*/
@Override
public int compare(Object o1, Object o2) {
Person obj1 = (Person)o1;
Person obj2 = (Person)o2;
int result = 0;
if(obj1.getAge() > obj2.getAge()) {
result = 1;
} else {
result = -1;
}
if(obj1.getAge() == obj2.getAge()) {
if(obj1.getHeight() > obj2.getHeight()){
result = 1;
}
}
return result;
}
}
이런 경우에
height 가 같은 경우에는 다루고 있지 않아서 에러를 내는 줄 알았는데..
Person에 age와 height 만 빼서 돌린 경우에는 에러안난다..
뭘까 . 항상 에러가 나는건 아닌 건가..
https://www.geeksforgeeks.org/timsort/
Comparator의 compare을 overriding 했을 때 위의 주석에 쓰여져 있는 부분을 보면 설명이 있음..
* The implementor must ensure that {@link Integer#signum
* signum}{@code (compare(x, y)) == -signum(compare(y, x))} for
* all {@code x} and {@code y}. (This implies that {@code
* compare(x, y)} must throw an exception if and only if {@code
* compare(y, x)} throws an exception.)<p>
* <p>
* The implementor must also ensure that the relation is transitive:
* {@code ((compare(x, y)>0) && (compare(y, z)>0))} implies
* {@code compare(x, z)>0}.<p>
* <p>
* Finally, the implementor must ensure that {@code compare(x,
* y)==0} implies that {@code signum(compare(x,
* z))==signum(compare(y, z))} for all {@code z}.
인터페이스를 구현한 클래스에서는 compare(x, y) 가 -1 이면 compare(y, z) 가 1 이어야 된다. -> 대칭성
인터페이스를 구현한 클래스에서는 추이성을 보장해야 한다. (transitivity) -> 추이성
인터페이스를 구현한 클래스에서는 compare(x, y) ==0 이면 compare(x, z) == compare(y, z) 어야 한다.
TimSort의 정렬 알고리즘을 사용할 때 중요한 것
1. 반사성 : a와 a를비교할 때 항상 같아야 한다. ( a == a )
2. 대칭성: a > b 라면 b < a 가 되어야 한다.
3. 추이성: a < b 이고 b < c 이면 a < c 여야 한다.
4. 일관성 : 두 객체 a와 b가 같다면, 다른 비교가 반복되어도 계속 같아야 한다. 즉, compare(a,b)가 0 이라면 a와 b가 변하지 않는 한 compare(a,b)가 항상 0이어야 한다.
비교 연산에서 중요한 성질로 네 가지를 모두 만족해야 Comparator가 안전하고 일관되게 사용될 수 있다.
--> 위배되면 어쩔때는 정렬되고 어쩔때는 안되는 상황이 발생할 수 있다.
내가 정렬에 에러를 마주쳤을 때 아래 메소드를 통해서 정렬한 경우에는 정렬이 잘 되었었다.
Comparator<Person> comparator = Comparator
.comparing(Person::getAge)
.thenComparing(Person::getHeight);
가독성도 좋은 듯.
Comparator class를 따로 구현했을 때는 들어가봐야하는데..
정렬할 때 기준을 정한다면 같은 경우, 작은경우, 큰경우 를 잘 숙고 해야 함.
유의하자.
'정보 > Language' 카테고리의 다른 글
[Javascript] Object, Array (0) | 2024.01.09 |
---|---|
Kotlin: Functions (0) | 2023.08.02 |
Kotlin: Control Flow (0) | 2023.07.31 |
Kotlin : Hello, world! (0) | 2023.07.20 |
Enum을 사용한 메뉴관리 (0) | 2022.08.26 |