[Java] Comparable vs Comparator


JavaでArrayssort()が呼び出されると、配列がソートされているように見えますが、実際にはComparableの実装によってソートされます.ComparableおよびComparatorは、比較対象に必要な方法を定義するインタフェースである.

💡 比較対象?


通常、基本タイプの変数については、記号を用いて容易に比較することができる.新しいクラスオブジェクトを作成して比較する場合は、どのように比較しますか?
class Person {
    private String name;
    private int age;

    public Person(String name, int age){
        this.name = name;
        this.age = age;
}
このようなPersonクラスを作成したとします.基本タイプとは異なり、等号として比較することはできず、nameageのどちらを基準に比較すべきか分かりません.
そのために設計されたのはComparableおよびComparatorである.では、2つのインタフェースの違いを見てみましょう.

Comparable

public interface Comparable<T> {
    public int compareTo(T o);
}
Comparableインタフェースは、compareToという名前の方法を使用してオブジェクトを比較する.compareToメソッドには、自身とパラメータオブジェクトを比較するためのパラメータが1つしかありません.メソッドの戻り値はintであり、比較する2つのオブジェクトが同じである場合、0は負の値を返し、比較値より大きい場合は正の値を返す必要があります.
PersonクラスからComparableインタフェースを継承し,compareToメソッドを実現する.
class Person implements Comparable<Person> {
    private String name;
    private int age;

    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }

    public int getAge(){
        return this.age;
    }

    @Override
    public String toString() {
        return "[" + name + ": " + age + "]";
    }

    @Override
    public int compareTo(Person o) {
        // Integer.compare(a,b)
        // a value less than 0 if x < y
        // a value greater than 0 if x > y
        return Integer.compare(this.age, o.getAge());
    }
}
Comparableインターフェースを実装し、compareTo方法をカバーした.2つのオブジェクトの値が等しい場合は0を返し、それ自体が大きい場合は正の値を返し、小さい場合は負の値を返します.
return this.age - o.getAge();
簡単に使えますが、底流またはオーバーフローの問題が発生する可能性があるので、直接比較したほうがいいです.Integerですcompare()メソッドを用いて比較を行いif文で比較しようとしたが,友好的なintelliJがこの関数を推奨した.Integer.比較()メソッドを参照してください.
public static int compare(int x, int y) {
    return (x < y) ? -1 : ((x == y) ? 0 : 1);
}

Comparator

public interface Comparator<T> {
    int compare(T o1, T o2);
}    
Comparableが自分と他のオブジェクトを比較した場合、Comparatorは2つの異なるオブジェクトを比較した.またComparableはjavaです.langパッケージに存在し、インポートする必要がない場合、Comparatorはjavaです.インポートするにはutilパッケージに存在する必要があります.Comparatorインタフェースを使用してPersonクラスを実装しましょう.
class Person implements Comparator<Person> {
    private String name;
    private int age;

    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }
    
    public String getName(){
        return this.name;
    }

    @Override
    public String toString() {
        return "[" + name + ": " + age + "]";
    }

    @Override
    public int compare(Person o1, Person o2) {
        return o1.getName().compareTo(o2.getName());
    }
}
Personクラスではcompareメソッドを使用できますが、比較用のオブジェクトしか作成できないという欠点があります.
public class ComparePractice {
	public static void main(String[] args)  {
 
		Person a = new Person("mark", 24);		
		Person b = new Person("jeno", 23);		
		Person c = new Person("jisung", 21);	
		Person comp = new Person("name", 0);		// 비교만을 위해 사용할 객체
			
		//           ⋁
		int isBig = comp.compare(a, b);
        //            ⋁
		int isBig2 = comp.compare(b, c);
		//            ⋁
		int isBig3 = comp.compare(a, c);
		
	}
    //... 생략
}
こんなふうに!
したがって、Comparatorは、通常、匿名オブジェクトを使用するか、比較機能を個別に実装するために比較クラスを作成する.
比較にのみ使用するクラスを作成します.
class nameSort implements Comparator<Person> {

    @Override
    public int compare(Person o1, Person o2) {
        // a value less than 0 if this string is lexicographically less than the string argument;
        // a value greater than 0 if this string is lexicographically greater than the string argument.
        return o1.getName().compareTo(o2.getName());
    }
}
Comparatorが指定されていない場合、sort()はオブジェクト実装のComparableに従ってソートされ、Comparatorが指定され、デフォルトのソート基準(Comparable)以外の基準でソートできます.

完全なコード

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ComparePractice {
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("mark", 24));
        personList.add(new Person("jeno", 23));
        personList.add(new Person("jisung", 21));

        Collections.sort(personList);
        System.out.println(personList);

        personList.sort(new nameSort());
        System.out.println(personList);
    }
}

class Person implements Comparable<Person> {
    private String name;
    private int age;

    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }

    public int getAge(){
        return this.age;
    }

    public String getName(){
        return this.name;
    }

    @Override
    public String toString() {
        return "[" + name + ": " + age + "]";
    }

    @Override
    public int compareTo(Person o) {
        // Integer.compare(a,b)
        // a value less than 0 if x < y;
        // a value greater than 0 if x > y
        return Integer.compare(this.age, o.getAge());
    }
}
class nameSort implements Comparator<Person> {

    @Override
    public int compare(Person o1, Person o2) {
        // a value less than 0 if this string is lexicographically less than the string argument;
        // a value greater than 0 if this string is lexicographically greater than the string argument.
        return o1.getName().compareTo(o2.getName());
    }
}

出力結果

// 나이 기준 오름차순 정렬
[[jisung: 21], [jeno: 23], [mark: 24]]

// 이름 기준 오름차순 정렬
[[jeno: 23], [jisung: 21], [mark: 24]]

📗 リファレンス


Javaの定番3 rd Edition
Java[JAVA]-CompabileとComparator