Comparable VS Comparator

22282 ワード

Javaで比較が必要な機能(ex.ソート)を実装する場合は、CompareableまたはComparatorを使用する必要があります.
参考にして判断する対象がある場合は、直接比較対象(comparable)に問い合わせるか、3番目の対象(comparator)に問い合わせることができます.
メソッドを再定義し、比較のためにメソッドを呼び出す必要があります.
ただし、比較的大きい場合は、次のようにして戻り値を決定する必要があります.
戻り値の意味
  • 負数-私は小さい
  • 0-両者は同じです.
  • 羊水-私は大きいです.
  • Comparable?


    オブジェクト自体を他のオブジェクトと比較する方法
    Compareableを実装するクラスは、Compareableインタフェースを使用するために作成されたコレクションインプリメンテーションと完全に互換性があります.
    比較時にcomparableに変換して比較するので、comparableを実現するオブジェクト間でしか比較できません.そうでない場合、ClassCastExceptionが放出されます.
    比べ物にならない子だけが比較できる.
    Javaプラットフォームライブラリに含まれるvalueclassのほとんどがComparableインタフェースを実装しています.

    CompareToを実施する際に注意すべき事項


    cf)sgn(expression)は、数学のsignum関数であり、-1、0、および1の値を返します.
    返される値は、式の値が負か正かによって異なります.
  • compareToを実現する場合、x、Yに対してsgn(x.compareTo(y)=-sgn(y.compareTo(x))を満たすべきである.
    ->どちらかに異常が発生した場合、もう一方にも異常が発生します.
  • compareToを実現するには、物性を満たす必要があります.
    (x.compareTo(y)>0&y.compareTo(z)>0)はx.compareTo(z)>0であるべきである.
  • 要約すると、x>yはyyはy>zはx>zは成立することを表す.
    以上のすべての事項はx.compareTo(y)=0の時にも成立しなければならない.
    compareToは同治性検査ではなく順番比較です.
    重要なのは、追加の(x.compareTo(y)==0)=(x.equals(y))を実現することです.
    このComparableは、Javaで組み込み関数として使用されるソートに標準を提供します.
    これらの条件は、Compareableインタフェースの正式なドキュメントを表示することで理解できます.
    このインタフェースはクラスの自然な順序に従うべきで、クラスのcompareTo方法も自然な比較方法を採用すべきである.
    とても自然な順序(原文naturalOrder)が少しぼやけています
    一体何が自然なのか.

    Comparentでの自然注文


    これに対する答えは、いくつかの例を見ると感じられます.
  • 文字
  • を辞書順に表示
  • 数字は昇順に
  • 並べられている.
    これらの約束に従う.
    約束を守らない順序(ex.逆順序ソートなど)はJavaの立場では自然ではなく、規定された約束以外の条件でソートしたいならcomparatorを使うべきです.

    Comparator


    コンパレータ使用時
    Compareableが実装されていない場合、または少し特殊な順序関係を使用する場合に使用できます.
    複数の条件にソートするには、comparatorで条件文で処理します.
    Comparatorを使用するとComparableのCompareToは無視されるため、比較するオブジェクトにComparatorがある場合でも、Comparatoで定義されたCompareeToではなく比較を確認します.
    最大の利点は、compareToを再定義することなく、必要に応じてソートできることです.

    サマリ


    店は私の家のほうが安いと言っていますが、比較すると
    コンパレータ
    ソートを行うアルゴリズム自体を変えるのではなく,比較の仕方を変えて決定順序の判断を変える.

    インプリメンテーション


    Comparable


    クラスを作成し、比較可能性を実装するには、次のようにします.
    public class Student implements Comparable<Student>//이걸 막으면 compareTo를 만들어놔도 안된다.
    {
        int no, score;
    
        public Student(int no, int score) {
            this.no = no;
            this.score = score;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "no=" + no +
                    ", score=" + score +
                    '}';
        }
        //  음수  내가 작다 --> 둘을 그대로
        //  0    둘이 같다 --> 둘을 그대로
        //  양수  내가 크다 --> 서로 바꿈
        //@Override
        public int compareTo(Student o) {
            if(this.score==o.score){
                if(this.no == no) return 0;
                return this.no>o.no?1:-1;
            }
            return this.score>o.score?-1:1;
        }
        @Override
        public int compareTo(Student o){
            return this.no - o.no;
            return o.no - this.no;
            return Integer.compare(this.no,o.no);
            return Integer.compare(o.no,this.no);
        }
    }
    cf)Integerは自己比較の方法を実施した.

    Comparator

    public class ComparatorTest {
        static class StudentComparator implements Comparator<Student>{
    
            @Override
            public int compare(Student o1, Student o2) {
                return 0;
            }
        }
        public static void main(String[] args) {
            Student[] students = {
                    new Student(1, 10),
                    new Student(3, 50),
                    new Student(2, 80),
                    new Student(4, 10)
            };
            System.out.println("정렬 전 : " + Arrays.toString(students));
            Arrays.sort(students,new StudentComparator());
            System.out.println("점수기준 오름차정렬 후 : " + Arrays.toString(students));
            Arrays.sort(students, new Comparator<Student>() {
                @Override
                public int compare(Student o1, Student o2) {
                    return o2.score-o1.score;
                }
            });
            Arrays.sort(students,
                //타입 유추가 가능하면 타입 생략 가능.
                (Student o1, Student o2)-> {
    
                ( o1,  o2)-> {
                    return o2.score-o1.score;
                }
                (o1,  o2)-> o2.score-o1.score
            );
            //다중 조건 정렬
            //block을 줘도 좋지만 삼항연산자로 잡고 가도 좋다.
            Arrays.sort(students,(o1,o2)->o2.score != o1.score? o2.score-o1.score:o2.no-o1.score);
            System.out.println("점수 기준 내림차순 정렬 후 :"+Arrays.toString(students));
    
            int[][] studentsArray = {
                    {1,10},
                    {3,50},
                    {2,80},
                    {4,10}
            };
            Arrays.sort(studentsArray, new Comparator<int[]>() {
                @Override
                public int compare(int[] o1, int[] o2) {
                    return o1[0]-o2[0];
                }
            });
            Arrays.sort(studentsArray,(o1, o2)->o1[0]-o2[0]);
    
        }
    }