JAVA比较器

在Java中经常会涉及到对象数组的排序问题,
那么就涉及到对象之间的比较问题

java实现对象排序的方式有两种:
自然排序: java.lang.Comparable
定制排序: java.lang.Comparator

1.说明:
Java中的对象,正常情况下,只能进行比较==或!=。
不能使用 > 或 < 的。
但是在开发场景中,我们需要对多个对象进行排序,
言外之意,就需要比较对象的大小。

如何实现?
使用两个接口中的任何一个: Comparable 或Comparator

2.Comparable接口的使用举例:自然排序(默认考虑这个)

2.1 像String、包装类等实现了Comparable接口,
重写了compareTo(obj)方法,给出了比较两个对象大小的方式

2.2 像String、包装类重写compareTo()方法以后,进行了从小到大的排列

2.3 重写compareTo(obj)的规则:
如果当前对象this大于形参对象bj,则返回正整数,
如果当前对象this小于形参对象obj,则返回负整数,
如果当前对象this等于形参对象obj,则返回零。

2.4 对于自定义来说,如果需要排序,
我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法。
在compareTo(obj)方法中指明如何排序

举例1:

@Test
public void test1(){
    String[] arr = new String[]{"A","G","E","B","C","H"};
    Arrays.sort(arr);
    System.out.println(Arrays.toString(arr));
    
}

结果: [A, B, C, E, G, H]

举例2:(自定义类)

public class Goods implements Comparable {
    private String name;
    private double price;
//省略无参构造,有参构造,getter和setter

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

//指明商品比较大小的方式:希望价格从低到高排序,再按照产品名称从高到低排序
    @Override
    public int compareTo(Object o) {
        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("传入的参数类型不一致");
//        运行时异常,可以考虑不去处理
    }
}

CompareTest

@Test
    public void test2(){
        Goods[] arr = new Goods[5];
        arr[0] = new Goods("MiTv",3500);
        arr[1] = new Goods("SonyTv",6500);
        arr[2] = new Goods("HuaWeiTv",5500);
        arr[3] = new Goods("SanXing",5000);
        arr[4] = new Goods("Tao",3500);
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
}

结果:
[Goods{name=‘Tao’, price=3500.0},
Goods{name=‘MiTv’, price=3500.0},
Goods{name=‘SanXing’, price=5000.0},
Goods{name=‘HuaWeiTv’, price=5500.0},
Goods{name=‘SonyTv’, price=6500.0}]

3.Comparator接口的使用:定制排序

3.1 背景:
当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,
或者实现了java. lang. Comparable接口的排序规则不适合当前的操作,
那么可以考虑使用Comparator的对象来排序

3.2 重写compare(object o1, object o2)方法,比较o1 和o2的大小:
如果方法返回正整数,则表示01大于o2;
如果返回0,表示相等;
返回负整数,表示o1小于o2。

举例1:

@Test
    public void test3(){
        String[] arr = new String[]{"A","G","E","B","C","H"};
        //下面是泛型去掉的操作
        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));
    }

结果: [H, G, E, C, B, A]

举例2:(自定义类)
引用上方类

@Test
public void test4(){
    Goods[] arr = new Goods[6];
    arr[0] = new Goods("MiTv",3500);
    arr[1] = new Goods("SonyTv",6500);
    arr[2] = new Goods("HuaWeiTv",5500);
    arr[3] = new Goods("SanXing",5000);
    arr[4] = new Goods("SanXing",7000);
    arr[5] = new Goods("Tao",3500);
    //指明商品比较大小的方式:希望产品名称从低到高排序,再按照价格从高到低排序
    //下面是有泛型并用Lambda表达式的操作
    Arrays.sort(arr, (o1, o2) -> {
        if (o1.getName().equals(o2.getName())){
            return -Double.compare(o1.getPrice(),o2.getPrice());
	//默认是从低到高,加上负,就变成了从高到底
        }else {
            return o1.getName().compareTo(o2.getName());
        }
    });
    System.out.println(Arrays.toString(arr));
}

结果:
[Goods{name=‘HuaWeiTv’, price=5500.0},
Goods{name=‘MiTv’, price=3500.0},
Goods{name=‘SanXing’, price=7000.0},
Goods{name=‘SanXing’, price=5000.0},
Goods{name=‘SonyTv’, price=6500.0},
Goods{name=‘Tao’, price=3500.0}]

Comparable接口与Comparator的使用的对比:
1.Comparable接口的方式一旦一定,
保证Comparable接口实现类的对象在任何位置都可以比较大小。

2.Comparator.接口属于临时性的比较。

常用类

Stream类
1.System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。

2.由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是static的,所以也可以很方便的进行调用。

3.成员变量
System类内部包含in、out和err三 个成员变量,
分别代表标准输入流(键盘输入),标准输出流(显示器)和标准错误输出流(显示器)。

4.成员方法

  1. native long currentTimeMillis():
    该方法的作用是返回当前的计算机时间
  2. void exit(int status):
    该方法的作用是退出程序。
    其中status的值为0代表正常退出,非零代表异常退出。
    使用该方法可以在图形界面编程中实现程序的退出功能等。
  3. void gc():
    该方法的作用是请求系统进行垃圾回收。
    至于系统是否立刻回收,
    则取决于系统中垃圾回收算法的实现以及系统执行时的情况。
  4. String getProperty(String key):
    该方法的作用是获得系统中属性名为key的属性对应的值。
    系统中常见的属性名以及属性的作用如下所示:
    java.version》Java运行时环境版本
    java.home》Java安装目录
    os.name》操作系统的名称
    os.version》操作系统的版本
    user.name》用户的账户名称
    user.home》用户的主目录
    user.dir》用户的当前工作目录

举例:

@Test
    public void test1(){
        String property = System.getProperty("java.version");
        System.out.println(property);
        String property1 = System.getProperty("java.home");
        System.out.println(property1);
        String property2 = System.getProperty("os.name");
        System.out.println(property2);
        String property3 = System.getProperty("os.version");
        System.out.println(property3);
}

结果:
1.8.0_241
D:\A\java\jdk\jre
Windows 10
10.0

BigInteger类和BigDecimal类

BigInteger类

Integer类作为int的包装类,能存储的最大整型值为2的31次方整体-1,Long类 也是有限的,最大为2的63次方整体-1。如果要表示再大的整数,不管是基本数据类型还是他们的包装类都无能为力,更不用说进行运算了。

java.math包的BigInteger可以表示不可变的任意精度的整数。

常用方法

  1. BigInteger(String val):根据字符串构建BigInteger对象
  2. BigInteger divide(BigInteger val):返回其值为(this/val)的BigInteger。整数相除只保留整数部分。

BigDecimal类
一般的Float类和Double类可以用来做科学计算或工程计算,
但在商业计算中, 要求数字精度比较高,故用到java.math.BigDecimal类 。

BigDecimal类支持不可变的、任意精度的有符号十进制定点数。

构造器

  1. public BigDecimal(double val)
  2. public BigDecimal(String val)

常用方法

  1. public BigDecimal multiply(BigDecimal multiplicand)
  2. public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)