예를 들어

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/ 

 

TimSort - Data Structures and Algorithms Tutorials - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org

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를 따로 구현했을 때는 들어가봐야하는데..

 

정렬할 때 기준을 정한다면 같은 경우, 작은경우, 큰경우 를 잘 숙고 해야 함.

 

유의하자. 

 

https://www.baeldung.com/java-8-comparator-comparing

'정보 > 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

+ Recent posts