天天看點

Java(3)--Collections排序(Comparable和Comparator接口的實作)前言接口分析程式示例反思總結

文章目錄

  • 前言
  • 接口分析
    • Comparable接口
    • Comparator接口
    • compareTo和compare方法
    • 相關之處
  • 程式示例
    • 調用預設的Comparable接口
    • 調用重寫compareTo方法的Comparable接口
      • 注意事項
    • 調用重寫compareTo方法的Comparator接口
    • 調用重寫compareTo方法的Comparator接口實作絕對值排序
  • 反思總結

前言

  • 包裝類Collections的排序方法可以運用到各種集合架構,非常友善
  • 分析看不懂請結合程式示例看
  • 有問題歡迎評論或者私信!!!

接口分析

Comparable接口

  • Comparable接口在 java.lang.Comparable 包下
  • Comparable接口的實作方法:public int compareTo(T t);
  • Comparable接口是在集合的(類的)内部實作的排序方式,調用的實質 t1.compareTo(t2);
  • 在排序對象本身支援互相比較所需要的接口(如Integer、String、Double、Float等)時,可以直接調用 Collections.sort() 方法的Comparable接口(參考程式示例)
  • 當數值或ASCII碼值從小到大的預設順序或者排序的根據對象不滿足程式需求時,可以重寫compareTo方法(參考程式示例)

Comparator接口

  • Comparator接口在 java.util.Comparator 包下
  • Comparator接口的實作方法:public int compare(T t1, T t2);
  • Comparator接口是在集合的(類的)外部實作的排序方式,需要用到一個比較容器,調用的實質是 compare(t1 , t2);(參考程式示例)
  • 在排序對象本身不支援互相比較所需要的接口,例如對整數采用絕對值大小排序,顯然對象本身的Integer自然排序是不能實作的,同時如果Integer類也不容許你在它的内部重寫compareTo()去改變它的排序行為,是以就可以用到Comparator接口(參考程式示例)

compareTo和compare方法

  • Comparable接口的實作方法:public int compareTo(T t),調用的實質 t1.compareTo(t2);

    在方法内部傳回一個運算結果,例如傳回:t1.x - t2.x,則按從小到大的順序排序

    若傳回:t2.x - t1.x,則按從大到小的順序排序

  • Comparator接口的實作方法:public int compare(T t1, T t2),調用的實質是 compare(t1 , t2);

    在方法内部傳回一個運算結果,例如傳回:t1.x - t2.x,則按從小到大的順序排序

    若傳回:t2.x - t1.x,則按從大到小的順序排序

  • compareTo預設的調用可以實作字元串的比較,比較方法:先比較第一個字元,不同則傳回ASCII碼的內插補點,若第一個字元相同,則比較第二個字元,若前面字元相同則比較長度。

    例如:

    String a = 'abc';
    String b = 'cde';
    String c = 'abcde';
    int d = a.compareTo(b);
    int e = a.compareTo(c);
               

​ 傳回d = -2,由a的ASCII碼值減去b的ASCII碼值得來。e = -2,因為前字元相同,a.length() - c.length() = -2.

相關之處

  • 對于一個對象的排序,既可以用Comparable接口實作,也能用Comparator接口實作,隻是兩種排序的實作方式不同,
  • 在某些情況的排序下,可以用Comparator接口,在接口的compare方法中再次調用compareTo方法進行比較。例如如下情況:
    輸入學生的學号、姓名、班級、成績,分别根據這四個資料進行排序。

​ 對學号的排序,可以調用Comparable接口重寫comparaTo方法按學号從小到大排序

​ 對姓名的排序,可以實作一個比較容器,在容器中重寫compare方法,在compare方法中調用compareTo方法實作對字元串的比較,然後傳回對字元串的比較結果。

class NameUPComparator implements java.util.Comparator {
    public int compare(Object o1, Object o2) {
        Student s1 = (Student)o1;// 轉化成目前類型的對象
        Student s2 = (Student)o2;
        return s1.getName().compareTo(s2.getName());
    }
}
           

在調用sort方法時,則要通過:

程式示例

調用預設的Comparable接口

import java.util.ArrayList;
import java.util.Collections;

public class CompObj {

    public String toString() {
        return "[x = " + x + "]";
    }

    public static void main(String[] args) {
        ArrayList<Integer> al = new ArrayList<Integer>();// 單一Integer資料的ArrayList,有本身支援比較的接口Integer
        al.add(3);
        al.add(1);
        al.add(2);
        System.out.println("Before sort!");
        for (int i = 0; i < al.size(); i++) {
            System.out.println(al.get(i));
        }
        Collections.sort(al); // 調用Collections的sort方法-靜态方法
        System.out.println("After sort!");
        for (int i = 0; i < al.size(); i++) {
            System.out.println(al.get(i));
        }
    }
}
           
Java(3)--Collections排序(Comparable和Comparator接口的實作)前言接口分析程式示例反思總結

調用重寫compareTo方法的Comparable接口

根據x值排序

import java.util.ArrayList;
import java.util.Collections;

public class CompObj implements java.lang.Comparable { // 定義要排序的類

    int x;
    int y;

    public CompObj(int n1, int n2) {
        x = n1;
        y = n2;
    }

    public String toString() {
        return "[x = " + x + ", y = " + y + "]";
    }

    public int compareTo(Object o) {
        CompObj co = (CompObj) o;
        if (this.x != co.x) {
            return this.x - co.x;
        } else {
            return this.y - co.y;
        }
    }

    public static void main(String[] args) {
        ArrayList<CompObj> al = new ArrayList<CompObj>();
        al.add(new CompObj(3, 1));
        al.add(new CompObj(1, 3));
        al.add(new CompObj(2, 2));
        al.add(new CompObj(2, 1));
        System.out.println("Before sort!");
        for (int i = 0; i < al.size(); i++) {
            System.out.println(al.get(i));
        }
        Collections.sort(al); // 調用Collections的sort方法-靜态方法
        System.out.println("After sort!");
        for (int i = 0; i < al.size(); i++) {
            System.out.println(al.get(i));
        }
    }

}
           
Java(3)--Collections排序(Comparable和Comparator接口的實作)前言接口分析程式示例反思總結

注意事項

  • compareTo()方法的形參為Object類的對象,在比較之前要進行類型轉換成為CompObj類的對象
  • 在重寫的compareTo方法中,若倆對象的x值相同,則比較y值
  • 若改為
    if (this.x != co.x) {
                return co.x - this.x;
            } else {
                return co.y - this.y;
            }
               
    則按照從大到小的順序排序

調用重寫compareTo方法的Comparator接口

根據y值排序

import java.util.ArrayList;
import java.util.Collections;

class ObjComparator implements java.util.Comparator {
    public int compare(Object o1, Object o2) {
        CompObj co1 = (CompObj) o1; // 轉化成目前類型的對象
        CompObj co2 = (CompObj) o2;
        if (co1.y != co2.y) {
            return co1.y - co2.y;// 先根據y值排序
        } else {
            return co1.x - co2.x;
        }
    }
}

public class CompObj { // 無需實作Comparable接口
    int x;
    int y;

    public CompObj(int n1, int n2) {
        x = n1;
        y = n2;
    }

    public String toString() {
        return "[x = " + x + ", y = " + y + "]";
    }

    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add(new CompObj(3, 2));
        al.add(new CompObj(1, 3));
        al.add(new CompObj(1, 2));
        System.out.println("Before sort!");
        for (int i = 0; i < al.size(); i++) {
            System.out.println(al.get(i));
        }
        Collections.sort(al, new ObjComparator());
        System.out.println("After sort!");
        for (int i = 0; i < al.size(); i++) {
            System.out.println(al.get(i));
        }
    }
}
           
Java(3)--Collections排序(Comparable和Comparator接口的實作)前言接口分析程式示例反思總結

調用重寫compareTo方法的Comparator接口實作絕對值排序

根據x的絕對值排序

import java.util.ArrayList;
import java.util.Collections;

class AbsComparator implements java.util.Comparator {
    public int compare(Object o1, Object o2) {
        CompObj co1 = (CompObj) o1;// 轉化成目前類型的對象
        CompObj co2 = (CompObj) o2;
        int v1 = Math.abs(co1.x);// 把對象co1的x成員轉化成絕對值
        int v2 = Math.abs(co2.x);
        return v1 - v2;
    }
}

public class CompObj { // 無需實作Comparable接口
    int x;
    int y;

    public CompObj(int n1, int n2) {
        x = n1;
        y = n2;
    }

    public String toString() {
        return "[x = " + x + ", y = " + y + "]";
    }

    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add(new CompObj(3, 2));
        al.add(new CompObj(-2, 3));
        al.add(new CompObj(1, 2));
        System.out.println("Before sort!");
        for (int i = 0; i < al.size(); i++) {
            System.out.println(al.get(i));
        }
        Collections.sort(al, new AbsComparator());
        System.out.println("After sort!");
        for (int i = 0; i < al.size(); i++) {
            System.out.println(al.get(i));
        }
    }
}

           
Java(3)--Collections排序(Comparable和Comparator接口的實作)前言接口分析程式示例反思總結

反思總結

  • 起床整到現在,餓的一批
  • 覺得有幫助到你就點個贊吧🙏🙏🙏
  • 下期出資料結構的約瑟夫問題