天天看點

Java對象的比較Comparable與Comparator

寫在前面,Java基礎系列文章都是作者基于b站尚矽谷的Java基礎視訊所做的筆記,沒有時間的同學可以認真看看,如果有時間的同學,還是建議看看視訊,畢竟筆記說到底還是自己的東西,每個人的習慣也是不一樣的,是以為了自己,學就對了,加油!

也請各位同學,如果感覺對自己有幫助,可以幫忙給個一鍵三連,謝謝!

文章目錄

  • ​​4.Java比較器​​
  • ​​4.1 概述​​
  • ​​4.2 Comparable自然排序舉例​​
  • ​​4.3 自定義類實作Comparable自然排序​​
  • ​​4.4 使用Comparator實作定制排序​​
  • ​​5.System類​​
  • ​​6.Math類​​
  • ​​7.BigInteger與BigDecimal​​

4.Java比較器

4.1 概述

/**
* 一、說明:Java中的對象,正常情況下,隻能進行比較:==  或  != 。不能使用 > 或 < 的
*          但是在開發場景中,我們需要對多個對象進行排序,言外之意,就需要比較對象的大小。
*          如何實作?使用兩個接口中的任何一個:Comparable 或 Comparator
*/      

Java實作對象排序的方式有兩種:

  • ​自然排序​

    ​​:​

    ​java.lang.Comparable​

  • ​定制排序​

    ​​:​

    ​java.util.Comparator​

4.2 Comparable自然排序舉例

/**
 * 一、說明:Java中的對象,正常情況下,隻能進行比較:==  或  != 。不能使用 > 或 < 的
 *    但是在開發場景中,我們需要對多個對象進行排序,言外之意,就需要比較對象的大小。
 *    如何實作?使用兩個接口中的任何一個:Comparable 或 Comparator
 *
 * 二、Comparable接口與Comparator接口的對比:
 *  Comparable接口的方式一旦指定,保證Comparable接口實作類的對象在任何位置都可以比較大小。
 *  Comparator接口屬于臨時性的比較。
 */
public class CompareTest {
    /*
    Comparable接口的使用舉例:  自然排序
    1.像String、包裝類等實作了Comparable接口,重寫了compareTo(obj)方法,給出了比較兩個對象大小的方式。
    2.像String、包裝類重寫compareTo()方法以後,進行了從小到大的排列
    3. 重寫compareTo(obj)的規則:
        如果目前對象this大于形參對象obj,則傳回正整數,
        如果目前對象this小于形參對象obj,則傳回負整數,
        如果目前對象this等于形參對象obj,則傳回零。
     */
    @Test
    public void test1(){
        String[] arr = new String[]{"AA","CC","KK","MM","GG","JJ","DD"};

        Arrays.sort(arr); //排序

        System.out.println(Arrays.toString(arr)); //[AA, CC, DD, GG, JJ, KK, MM]
    }
}      

4.3 自定義類實作Comparable自然排序

/**
 * 一、說明:Java中的對象,正常情況下,隻能進行比較:==  或  != 。不能使用 > 或 < 的
 *    但是在開發場景中,我們需要對多個對象進行排序,言外之意,就需要比較對象的大小。
 *    如何實作?使用兩個接口中的任何一個:Comparable 或 Comparator
 *
 * 二、Comparable接口與Comparator接口的對比:
 *  Comparable接口的方式一旦指定,保證Comparable接口實作類的對象在任何位置都可以比較大小。
 *  Comparator接口屬于臨時性的比較。
 */
public class CompareTest {
  
      /**
     * 4.對于自定義類來說,如果需要排序,我們可以讓自定義類實作Comparable接口,重寫compareTo(obj)方法。
     *   在compareTo(obj)方法中指明如何排序
     */
    @Test
    public void test2(){
        Goods[] arr = new Goods[5];
        arr[0] = new Goods("lenovoMouse",34);
        arr[1] = new Goods("dellMouse",43);
        arr[2] = new Goods("xiaomiMouse",12);
        arr[3] = new Goods("huaweiMouse",65);
        arr[4] = new Goods("microsoftMouse",43);

        Arrays.sort(arr); //排序

        System.out.println(Arrays.toString(arr));
    }
}      

Goods類

/**
 * 商品類
 */
public class Goods implements Comparable{

    private String name;
    private double price;

    public Goods() {
    }

    public Goods(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }

    //指明商品比較大小的方式:按照價格從低到高排序,
    //如果價格相同,再按照産品名稱從高到低排序(從高到低,可以直接在前面加負号"-")
    @Override
    public int compareTo(Object o) {
//        System.out.println("**************");
        if(o instanceof Goods){
            Goods goods = (Goods)o;
            //方式一:
            if(this.price > goods.price){
                return 1;
            }else if(this.price < goods.price){
                return -1;
            }else{
//                return 0;
               return -this.name.compareTo(goods.name);
            }
            //方式二:
//           return Double.compare(this.price,goods.price);
        }
//        return 0;
        throw new RuntimeException("傳入的資料類型不一緻!");
    }
}      

4.4 使用Comparator實作定制排序

/**
 * 一、說明:Java中的對象,正常情況下,隻能進行比較:==  或  != 。不能使用 > 或 < 的
 *    但是在開發場景中,我們需要對多個對象進行排序,言外之意,就需要比較對象的大小。
 *    如何實作?使用兩個接口中的任何一個:Comparable 或 Comparator
 *
 * 二、Comparable接口與Comparator接口的對比:
 *  Comparable接口的方式一旦指定,保證Comparable接口實作類的對象在任何位置都可以比較大小。
 *  Comparator接口屬于臨時性的比較。
 */
public class CompareTest {
  
    /*
    Comparator接口的使用:定制排序
    1.背景:
    當元素的類型沒有實作java.lang.Comparable接口而又不友善修改代碼,
    或者實作了java.lang.Comparable接口的排序規則不适合目前的操作,
    那麼可以考慮使用 Comparator 的對象來排序
    2.重寫compare(Object o1,Object o2)方法,比較o1和o2的大小:
    如果方法傳回正整數,則表示o1大于o2;
    如果傳回0,表示相等;
    傳回負整數,表示o1小于o2。
     */
    @Test
    public void test3(){
        String[] arr = new String[]{"AA","CC","KK","MM","GG","JJ","DD"};
        Arrays.sort(arr,new Comparator(){

            //按照字元串從大到小的順序排列
            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof String && o2 instanceof  String){
                    String s1 = (String) o1;
                    String s2 = (String) o2;
                    //預設從小到大,前面加上"-"表示從大到小
                    return -s1.compareTo(s2);
                }
//                return 0;
                throw new RuntimeException("輸入的資料類型不一緻");
            }
        });
        System.out.println(Arrays.toString(arr));
    }

    @Test
    public void test4(){
        Goods[] arr = new Goods[6];
        arr[0] = new Goods("lenovoMouse",34);
        arr[1] = new Goods("dellMouse",43);
        arr[2] = new Goods("xiaomiMouse",12);
        arr[3] = new Goods("huaweiMouse",65);
        arr[4] = new Goods("huaweiMouse",224);
        arr[5] = new Goods("microsoftMouse",43);

        Arrays.sort(arr, new Comparator() {
            //指明商品比較大小的方式:按照産品名稱從低到高排序,再按照價格從高到低排序
            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof Goods && o2 instanceof Goods){
                    Goods g1 = (Goods)o1;
                    Goods g2 = (Goods)o2;
                    if(g1.getName().equals(g2.getName())){
                        return -Double.compare(g1.getPrice(),g2.getPrice());
                    }else{
                        return g1.getName().compareTo(g2.getName());
                    }
                }
                throw new RuntimeException("輸入的資料類型不一緻");
            }
        });

        System.out.println(Arrays.toString(arr));
    }

}      

5.System類

  • System類代表系統,系統級的很多屬性和控制方法都放置在該類的内部。 該類位于​

    ​java.lang包​

    ​。
  • 由于該類的構造器是​

    ​private​

    ​​的,是以​

    ​無法建立該類的對象​

    ​​,也就是​

    ​無法執行個體化該類​

    ​​。其内部的​

    ​成員變量和成員方法都是static的​

    ​,是以也可以很友善的進行調用。
  • 成員變量
  • System類内部包含in、out和err三個成員變量,分别代表标準輸入流 (鍵盤輸入),标準輸出流(顯示器)和标準錯誤輸出流(顯示器)。
  • 成員方法
  • native long currentTimeMillis( ): 該方法的作用是傳回目前的計算機時間,時間的表達格式為目前計算機時 間和GMT時間(格林威治時間)1970年1月1号0時0分0秒所差的毫秒數。
  • void exit(int status): 該方法的作用是退出程式。其中status的值為0代表正常退出,非零代表異常退出。使用該方法可以在圖形界面程式設計中實作程式的退出功能等。
  • void gc( ): 該方法的作用是請求系統進行垃圾回收。至于系統是否立刻回收,則取決于系統中垃圾回收算法的實作以及系統執行時的情況。
  • String getProperty(String key): 該方法的作用是獲得系統中屬性名為key的屬性對應的值。系統中常見的屬性名以及屬性的作用如下表所示:
  • Java對象的比較Comparable與Comparator
/**
 * 其他常用類的使用
 * 1.System
 * 2.Math
 * 3.BigInteger 和 BigDecimal
 */
public class OtherClassTest {

    @Test
    public void test1() {
        String javaVersion = System.getProperty("java.version");
        System.out.println("java的version:" + javaVersion);

        String javaHome = System.getProperty("java.home");
        System.out.println("java的home:" + javaHome);

        String osName = System.getProperty("os.name");
        System.out.println("os的name:" + osName);

        String osVersion = System.getProperty("os.version");
        System.out.println("os的version:" + osVersion);

        String userName = System.getProperty("user.name");
        System.out.println("user的name:" + userName);

        String userHome = System.getProperty("user.home");
        System.out.println("user的home:" + userHome);

        String userDir = System.getProperty("user.dir");
        System.out.println("user的dir:" + userDir);

    }
}      

6.Math類

java.lang.Math提供了一系列靜态方法用于科學計算。其方法的參數和傳回 值類型一般為double型。
abs   絕對值
acos,asin,atan,cos,sin,tan   三角函數
sqrt   平方根
pow(double a,doble b)   a的b次幂
log   自然對數
exp   e為底指數
max(double a,double b)
min(double a,double b)
random()   傳回0.0到1.0的随機數
long round(double a)   double型資料a轉換為long型(四舍五入)
toDegrees(double angrad)   弧度—>角度 
toRadians(double angdeg)   角度—>弧度      

7.BigInteger與BigDecimal

  • Integer類作為int的包裝類,能存儲的最大整型值為2^31 -1,Long類也是有限的, 最大為2^63 -1。如果要表示再大的整數,不管是基本資料類型還是他們的包裝類 都無能為力,更不用說進行運算了。
  • java.math包的BigInteger可以表示不可變的任意精度的整數。BigInteger 提供 所有 Java 的基本整數操作符的對應物,并提供 java.lang.Math 的所有相關方法。 另外,BigInteger 還提供以下運算:模算術、GCD 計算、質數測試、素數生成、 位操作以及一些其他操作。
  • 構造器
  • BigInteger(String val):根據字元串建構BigInteger對象
  • 常用方法
  • 一般的Float類和Double類可以用來做科學計算或工程計算,但在商業計算中,要求數字精度比較高,故用到java.math.BigDecimal類。
  • BigDecimal類支援不可變的、任意精度的有符号十進制定點數。
  • 構造器
  • public BigDecimal(double val)
  • public BigDecimal(String val)
  • 常用方法
  • public BigDecimal add(BigDecimal augend)
  • public BigDecimal subtract(BigDecimal subtrahend)
  • public BigDecimal multiply(BigDecimal multiplicand)
  • public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
/**
 * 其他常用類的使用
 * 1.System
 * 2.Math
 * 3.BigInteger 和 BigDecimal
 */
public class OtherClassTest {

    @Test
    public void test2() {
        BigInteger bi = new BigInteger("1243324112234324324325235245346567657653");
        BigDecimal bd = new BigDecimal("12435.351");
        BigDecimal bd2 = new BigDecimal("11");
        System.out.println(bi);
//         System.out.println(bd.divide(bd2));
        System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP));
        System.out.println(bd.divide(bd2, 25, BigDecimal.ROUND_HALF_UP));

    }
}