Java内部比較器と外部比較器+匿名内部クラスの詳細説明


文書ディレクトリ
  • 一.コンパレータの定義
  • 二.内部比較器と外部比較器とは何ですか.
  • 3.なぜ2つの比較器が必要なのですか?
  • 4.comparable内部比較器
  • 4.1 intタイプ比較:
  • 4.2 Stringタイプ比較:
  • 4.3 doubleタイプ比較
  • 5.comparator外部比較器
  • 六.外部比較器と匿名内部クラスとの結合アプリケーション
  • 七.まとめ:
  • 引用:Javaで比較二文字といえば、equals()メソッドを用いて2つの数値が等しいかどうかを比較することが考えられますが、これは数値に対する操作にすぎず、他のデータ型と比較できないため、ComparatorまたはComparableで順序(つまりソート)を比較します.
    一.比較器の定義
    2つのオブジェクト間のサイズ関係や配列順序を決定することを比較と呼び,この比較機能を実現できるクラスやメソッドを比較器と呼ぶ.
    二.内部比較器と外部比較器とは何ですか.
  • 内部比較器はcomparableインタフェース
  • である.
  • 外部比較器はcomparatorインタフェース
  • である.
    三.なぜ2つの比較器が必要なのか.
    四.Comparable内部比較器
    4.1 intタイプ比較:
    まず、intタイプの数を比較するには、2つの数だけ差をつける必要があります.差が0より大きいと、aはbより大きいです.差が0より小さい場合、aはbより小さい.
    4.2 Stringタイプ比較:
    次にStringタイプの比較を見てみましょう.
    public class ComparableTest
    {
    
    	public static void main(String[] args)
    	{
    		
           String a="A";
           String b="B";
           
           System.out.println(a.compareTo(b));
    
    	}
    
    }
    

    Stringタイプではa-bはできませんが、Javaでは2文字のASCIIコードサイズを比較するcompareTo()メソッドが提供されています.比較した数が比較した数より小さい場合は-1を返します.
    Output:
    -1
    

    次に,Javaが提供するStringタイプのcomparaTo()メソッドからJavaの内部比較器構造を探究する.まずcompareTo()メソッドのソースコードに入ります.
    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence {
        
        public int compareTo(String anotherString) {  
            int len1 = value.length;
            int len2 = anotherString.value.length;
            int lim = Math.min(len1, len2);
            char v1[] = value;
            char v2[] = anotherString.value;
    
            int k = 0;
            while (k < lim) {
                char c1 = v1[k];
                char c2 = v2[k];
                if (c1 != c2) {
                    return c1 - c2;
                }
                k++;
            }
            return len1 - len2;
        }
    }
    
  • このコードから分かるように、戻り値はintタイプ、return len1 - len2;であり、文字列ASCIIコードの差分値を返し、比較された数よりも比較された数が小さい場合は−1を返し、そうでなければ1を返し、すなわちa.comparaTo(b)aが小さい場合は−1を返し、aが大きい場合は1を返す.
  • このcompareTo()メソッドは実装クラスのメソッドであり、Comparableインタフェースを実装する:
  • public interface Comparable<T> {
        public int compareTo(T o);
    }
    

    4.3 doubleタイプ比較
    次にdoubleタイプのサイズの比較方法を見てみましょう.
    public class ComparableTest
    {
    
    	public static void main(String[] args)
    	{
    		
           double a=1.2;
           double b=2.4;
           
           System.out.println(((Double)a).compareTo((Double)b));
    
    	}
    
    }
    

    Output:
    -1
    

    質問:なぜdoubleタイプのaとbをDoubleタイプに変換してcompareTo()メソッドを呼び出すのでしょうか.まず、Doubleとは何ですか(頭文字の大文字と小文字に注意).
  • doubleは基本タイプデータであり、Doubleは基本タイプdoubleのパッケージクラスであり、オブジェクトである.
  • 両者は加算できません.Doubleタイプで.doubleValue()メソッドを使用してdoubleタイプ数を取得できます.

  • Doubleはクラス(パッケージクラス)であることがわかりました.ソースコードを見てみましょう.
    public final class Double extends Number implements Comparable<Double> {
    
       public int compareTo(Double anotherDouble) {
            return Double.compare(value, anotherDouble.value);
        }
      }
    

    このセグメントコードのComparable< Double>は、Stringタイプと同様にクラスを実装する方法であり、Comparableインタフェースを実装することを示す.
    doubleタイプ比較では,aとbをクラスのオブジェクトに変換し,compareTo()メソッドを呼び出すことに相当する.
    上記はJavaが書いた特定のデータ型に対する比較器ですが、私たちは自分でデータ型を定義するときに、比較器を書き換えるべきです.
    テンプレート:
    Class B implements Comparable{
        
        int comparaTo(B b){
        	//return             
            return 
        }
    }
    

    例:
    public class Student implements Comparable{	
    	
    	 String name;
    	 int age;
    	 
    	public Student(){}
    	
    	public Student(String name, int age)
    	{
    		super();
    		this.name = name;
    		this.age = age;
    	}
    
    	@Override
    	public int compareTo(Object o)
    	{
    		//      , :a.ComparaTo(b)
    		//a   comparaTo()  ,       this  
    		//b       compareTo(Object o),  b object  ,         student     age  
    		Student stu=(Student) o;
    		return this.age - stu.age;
    	}
    	
    }
    
    class Test{
    	public static void main(String []args) {
    		Student a = new Student("Ahana",18);
    		Student b = new Student("Babily",19);
    		
    		System.out.println(a.compareTo(b));
    	}
    }
    

    Output:
    -1
    

    に注意⚠️1:Studentクラスを書く時、public class Studentの後でimplements Comparableをプラスして、その中でComparableはスペルに注意します!!!Cは大文字!!!に注意⚠️2:名前を比較する場合は、JavaデフォルトのcompareTo()をそのまま使えばよい
    return this.name compareTo( stu.name);
    

    属性が1つでない場合はどうすればいいですか??例えば名前を比較して、年齢が同じなら、年齢を比較したいのですが、どうすればいいですか?
    @Override
    	public int compareTo(Object o)
    	{
    		Student stu=(Student) o;
    		if( this.name.compareTo(stu.name) != 0) {  //        ,    ,   ,     。
    			return this.name.compareTo(stu.name);
    		}else {
    				return this.age-stu.age;
    			}
    		}
    

    OK、クラスがComparableインタフェースを実装した場合、クラスオブジェクトのセット、または配列はツールクラスを使用してソートできます.Arrays.sort(配列,null),Collections.sort(集合,null)を用いてソートできます.
    5.comparator外部比較器
    外部比較器は匿名オブジェクトとよく関連しています.まず、匿名オブジェクトの外部比較器が入っていないことを見てみましょう.
    例:
    import java.util.Comparator;
    
    public class Student {	
    	
    	 String name;
    	 int age;
    	 
    	public Student(){}
    	
    	public Student(String name, int age)
    	{
    		super();
    		this.name = name;
    		this.age = age;
    	}
    
    
    }
    
    class OutsideComparator implements Comparator{
    
    	@Override
    	public int compare(Object o1, Object o2)
    	{
    		Student a1 =((Student)o1);
    		Student a2 =((Student)o2);
    		//      
    		return a1.age - a2.age;
    	}
    class OutsideComparator1 implements Comparator{
    
    	@Override
    	public int compare(Object o1, Object o2)
    	{
    		Student a1 =((Student)o1);
    		Student a2 =((Student)o2);
    		//      
    		return a1.name.compareTo(a2.name);
    	}
    	
    
    }
    
    class Test{
    	public static void main(String []args) {
    		Student a = new Student("Ahana",18);
    		Student b = new Student("Babily",19);
    		
    		OutsideComparator oc = new OutsideComparator();
    		int result = oc.compare(a, b);
    		System.out.println(result);	
    		
    		OutsideComparator oc1 = new OutsideComparator();
    		int result1 =oc1.compare(a, b);
    		System.out.println(result1)
    	}
    }
    

    Output:
    -1
    -1
    

    注意事項⚠️:
  • 1.外部比較器はclassを新規作成し、implements Comparatorは、Comparatorの先頭文字が大文字であることに注意し、パケットimport java.util.Comparator;
  • をインポートする.
  • .compare(Object o 1,Object o 2)メソッドを書き換える場合、入力されるパラメータはすべてobjectタイプであるため、タイプ変換が必要であり、比較を行う.前の例では、Studentタイプに変換しました.
  • 3.外部比較器を用いて比較する場合、新規オブジェクトOutsideComparator oc = new OutsideComparator();はocを用いてcompare(Object o 1,Object o 2)メソッドを呼び出す.
  • 4.oc.compare(a,b);の結果はintタイプなので、intで返された結果を受け入れます.
  • 5.外部比較器は、異なるclassで異なる比較方法を書き、テストクラスで異なるオブジェクトを確立し、それぞれのcompare()方法を呼び出すだけで比較を実現することができる.このことから,外部比較器の拡張性がより良好であることが分かる.
  • 6.便宜上、複数の外部比較器が同時に存在する場合、オブジェクトの作成時にComparator com = new OutsideComparator();Comparator com = new OutsideComparator1(); Comparatorがインタフェースであり、OutsideComparatorとOutsideComparator 1が実装クラスであり、comオブジェクトがcomparare()メソッドを呼び出す際に実装クラスを呼び出す方法は、実際にはマルチステートの応用である.
  • 		Comparator bj = new OutsideComparator(); //            ,   Comparator bj = new OutsideComparator1();
    		int result2 = bj.compare(a, b);
    		System.out.println(result2);
    

    六.外部比較器と匿名内部クラスの結合応用
    外部比較器を書くときに、1つの属性をソートする必要があるときにclassを別に書く必要があり、オブジェクトを作成し、メソッドを呼び出すのが面倒であることがわかりました.次に、匿名オブジェクトを外部比較器と結合する簡単な方法を紹介します.
    import java.util.Comparator;
    
    class Test{
    	public static void main(String []args) {
    		Student a = new Student("Ahana",18);
    		Student b = new Student("Babily",19);
    		
    		
    		Comparator bj = new Comparator() { //              (Comparator)  
    
    			@Override
    			public int compare(Object o1, Object o2)
    			{
    				Student a1 =((Student)o1);
    				Student a2 =((Student)o2);
    				//      
    				return a1.age - a2.age;
    			} 
    		};
    		
    		int result = bj.compare(a, b);
    		System.out.println(result);
    		
    			
    	}
    }
    

    に注意⚠️:フォーマットComparator xxxx=new Comparator(){public int comparare(Object o 1,Object o 2){return xxxxx;};
    classを追加する必要はありません
    アップグレード:
    import java.util.Comparator;
    
    class Test{
    	public static void main(String []args) {
    		Student a = new Student("Ahana",18);
    		Student b = new Student("Babily",19);
    		
    		
    		int res = new Comparator() {
    
    			@Override
    			public int compare(Object o1, Object o2)
    			{
    				Student a1 =((Student)o1);
    				Student a2 =((Student)o2);
    				//      
    				return a1.age - a2.age;
    				
    			}
    			
    		}.compare(a, b);
    		
    		System.out.println(res);
    		
    			
    	}
    }
    

    分割して解析する
    new Comparator() {
    
    			@Override
    			public int compare(Object o1, Object o2)
    			{
    				Student a1 =((Student)o1);
    				Student a2 =((Student)o2);
    				//      
    				return a1.age - a2.age;
    				
    			}
    			
    		}
    

    このコードは、Comparatorのオブジェクトnew Comparator(){......}を確立したと言います.
    new Comparator() {
    
    			@Override
    			public int compare(Object o1, Object o2)
    			{
    				Student a1 =((Student)o1);
    				Student a2 =((Student)o2);
    				//      
    				return a1.age - a2.age;
    				
    			}
    			
    		}.compare(a, b);
    

    次に、新しいオブジェクトがcompare(a,b)を呼び出す.方法,new Comparator(){......}.comparator(a,b);
    int res = new Comparator() {
    
    			@Override
    			public int compare(Object o1, Object o2)
    			{
    				Student a1 =((Student)o1);
    				Student a2 =((Student)o2);
    				//      
    				return a1.age - a2.age;
    				
    			}
    			
    		}.compare(a, b);
    

    このセグメントコードは、int res=new Comparator(){......}.comparare(a,b);intタイプresで返される結果を受け入れます.
    七.まとめ:
    外部コンパレータを使用するか、外部コンパレータを使用するかは、必要に応じて決まります.要するに、外部コンパレータは内部コンパレータよりも柔軟で、メンテナンスが容易です.