天天看点

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));

    }
}