Java基础知识-第11章-Java比较器及常见类介绍

394 阅读10分钟

导图

image.png

1、Comparable/Comparator类

1.1、Java的比较器概述

Java中的对象,正常情况下,只能进行比较:==!= 。不能使用 >< 的,但是在Java中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题。

Java实现对象排序的方式有两种: 使用两个接口中的任何一个

  • 自然排序:java.lang.Comparable
  • 定制排序:java.util.Comparator

1.2、自然排序:java.lang.Comparable

1.2.1、概述

Comparable接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序。实现 Comparable 的类必须实现 compareTo(Object obj) 方法。默认都是从小到大排列的

使用步骤

  • 让要排序的类实现cmparable接口
  • 重写comparaTo()方法(可以用String 中的方法)

说明:

  • 像String、包装类等实现了Comparable接口,重写了compareTo(obj)方法,给出了比较两个对象大小的方式。
  • 像String、包装类重写compareTo()方法以后,进行了从小到大的排列
  • 重写compareTo(obj) 的规则:
    • 如果当前对象this大于形参对象obj,则返回正整数,
    • 如果当前对象this小于形参对象obj,则返回负整数,
    • 如果当前对象this等于形参对象obj,则返回零。

实例1:

@Test  
public void test1(){  
    String[] arr = new String[]{"AA","CC","KK","MM","GG","JJ","DD"};  
    // String里面实现了comparable接口,重写了compareto方法,所以排序成功(从小到大)
    Arrays.sort(arr); //[AA, CC, DD, GG, JJ, KK, MM] 
    System.out.println(Arrays.toString(arr));
}

1.2.2、自定义类实现自然排序

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

实例2: 让要排序的类实现cmparable接口,重写comparaTo()方法

public class Goods implements Comparable{
    String name;
    double price;
    int salas;

    public Goods() {
        super();
    }

    public Goods(String name, double price, int salas) {

        this.name = name;
        this.price = price;
        this.salas = salas;
    }

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

    //按照价格从低到高排序,再按照产品名称从高到低排序
    @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 -this.name.compareTo(goods.name);//调用String类的comparaTo()
            }

            //方法二:
            /*
            return Double.compare(this.price,goods.price);
            */
        }
        return 0;
    }
}

测试:

import java.util.Arrays;
public class goodTest {
    @Test
    public void test1(){
        Goods[] arr = new Goods[4];
        arr[0] = new Goods("联想",4000,15);
        arr[1] = new Goods("苹果",10000,100);
        arr[2] = new Goods("华为",5000,150);
        arr[3] = new Goods("华硕",6000,200);
        Arrays.sort(arr); 
        System.out.println(Arrays.toString(arr));
    }
}

1.3、定制排序:java.util.Comparator

1.3.1、概述

当元素的类型没有实现 java.lang.Comparable 接口而又不方便修改代码,了 或者实现了java.lang.Comparable 接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来 排序,强行对多个对象进行整体排序的比较。

使用步骤

  • new 一个Comparator对象
  • 定义一个compara(Object obj1,Object obj2)方法

重写compare(Object o1,Object o2)方法,比较o1和o2的大小:

  • 如果方法返回正整数,则表示o1大于o2;
  • 如果返回0,表示相等;
  • 返回负整数,表示o1小于o2。

注:

  • 调用String类的comparaTo()方法,从小到大排列要在返回值前加负号
  • 可以将 Comparator 对象传递给 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。
  • 还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的顺序,或者为那些没有自然顺序的对象 collection 提供排序。

1.3.2、定制排序实例

示例1:对String实现定制排序,让他从大大小排列

@Test
public void test2(){
    String[] arr = new String[]{"DD","CC","BB","AA"};

    //由于只使用一次,使用匿名内部类
    //按照字符串从小到大顺序排列
    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);//从小到大排列要加负号
            }
            throw new RuntimeException("输入的数据类型不一致");
        }
    });
    System.out.println(Arrays.toString(arr));
}

实例2:对前面goods类实现定制排序

@Test
public void test(){
    Goods[] arr = new Goods[5];
    arr[0] = new Goods("华为",4000,15);
    arr[1] = new Goods("苹果",10000,100);
    arr[2] = new Goods("联想",4000,150);
    arr[3] = new Goods("华硕",6000,200);
    arr[4] = new Goods("华硕",10000,100);

    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.name.equals(g2.name)){//如果名字一样
                    return -Double.compare(g1.price,g2.price);
                }else{
                    return g1.name.compareTo(g2.name);
                }
            }
            throw new RuntimeException("输入的数据类型不一致");
        }
    });
    System.out.println(Arrays.toString(arr));
}

1.4、Comparable接口和Comparator接口的对比

  • Comparable是让所处的类去实现,Comparable接口的方式一旦确定,实现类对象在任何位置都可以比较大小。
  • Comparator接口属于临时比较,是临时给的排序方式(匿名的类)

2、System类

2.1、概述

  • 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的属性对应的值。系统中常见 的属性名以及属性的作用如下表所示:

image.png

2.2、实例

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

}

3、Math类

java.lang.Math 提供一系列的静态方法用于科学计算。其方法的参数和返回值类型一般为double

方法描述
abs()绝对值
acosa(),asin(),atan(),cos(),sin(),tan()三角函数
sqrt()平方根
pow(double a, double b)a的b次幂
log()自然对数
exp()e为底指数
max(double a, dobule b)返回a,b间最大的一个的值
min(double a, double b)返回最小值
random()返回0.0~1.0的随机数
long round(double a)double 型的数据a转换成long型(四舍五入)
toDegrees(double angrad)弧度->角度
toRadians(double angdeg)角度-弧度

补充方法:Math 的 floorroundceil 方法实例比较

  • floor()返回小于等于(<=)给定参数的最大整数 。
  • ceil()返回大于等于( >= )给定参数的的最小整数,类型为双精度浮点型。
  • round()它表示四舍五入,算法为 Math.floor(x+0.5),即将原来的数字加上 0.5 后再向下取整,所以,Math.round(11.5) 的结果为12,Math.round(-11.5) 的结果为-11。
参数Math.floorMath.roundMath.ceil
1.4112
1.5122
1.6122
-1.4-2-1-1
-1.5-2-1-1
-1.6-2-2-1

4、BigInteger类

背景:

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

介绍

  • java.math包的BigInteger可以表示不可变的任意精度的整数。
  • BigInteger 提供所有 Java 的基本整数操作符的对应物,并提供 java.lang.Math 的所有相关方法。
  • 另外,BigInteger 还提供以下运算:模算术、GCD 计算、质数测试、素数生成、位操作以及一些其他操作。

构造器

  • BigInteger(String val):根据字符串构建BigInteger对象

常用方法

public BigInteger abs():返回此 BigInteger 的绝对值的 BigInteger。

BigInteger add(BigInteger val) :返回其值为 (this + val) 的 BigInteger

BigInteger subtract(BigInteger val) :返回其值为 (this - val) 的 BigInteger

BigInteger multiply(BigInteger val) :返回其值为 (this * val) 的 BigInteger

BigInteger divide(BigInteger val) :返回其值为 (this / val) 的 BigInteger。整数相除只保留整数部分。

BigInteger remainder(BigInteger val) :返回其值为 (this % val) 的 BigInteger。

BigInteger[] divideAndRemainder(BigInteger val):返回包含 (this / val) 后跟(this % val) 的两个 BigInteger 的数组。

BigInteger pow(int exponent) :返回其值为 (thisexponent) 的 BigInteger。

5、BigDecimal类

背景:

一般的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)

使用举例

public void testBigInteger() {

    BigInteger bi = new BigInteger("12433241123");
    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, 15, BigDecimal.ROUND_HALF_UP));

}

6、Character 包装类

参考www.runoob.com/java/java-c…

Character 类用于对单个字符进行操作。Character 类在对象中包装一个基本类型 char 的值

实例

char ch = 'a';
 
// Unicode 字符表示形式
char uniChar = '\u039A'; 
 
// 字符数组
char[] charArray ={ 'a', 'b', 'c', 'd', 'e' };

然而,在实际开发过程中,我们经常会遇到需要使用对象,而不是内置数据类型的情况。为了解决这个问题,Java语言为内置数据类型char提供了包装类Character类。

Character类提供了一系列方法来操纵字符。你可以使用Character的构造方法创建一个Character类对象,例如:

Character ch = new Character('a');

在某些情况下,Java编译器会自动创建一个Character对象。例如,将一个char类型的参数传递给需要一个Character类型参数的方法时,那么编译器会自动地将char类型参数转换为Character对象。 这种特征称为装箱,反过来称为拆箱

实例

// 原始字符 'a' 装箱到 Character 对象 ch 中
Character ch = 'a';
 
// 原始字符 'x' 用 test 方法装箱
// 返回拆箱的值到 'c'
char c = test('x');

转义序列

前面有反斜杠(\)的字符代表转义字符,它对编译器来说是有特殊含义的。

下面列表展示了Java的转义序列:

转义序列描述
\t在文中该处插入一个tab键
\b在文中该处插入一个后退键
\n在文中该处换行
\r在文中该处插入回车
\f在文中该处插入换页符
'在文中该处插入单引号
"在文中该处插入双引号
\在文中该处插入反斜杠

实例

当打印语句遇到一个转义序列时,编译器可以正确地对其进行解释。以下实例转义双引号并输出:

public class Test {
 
   public static void main(String[] args) {
      System.out.println("访问\"菜鸟教程!\"");
   }
}

以上实例编译运行结果如下:

访问"菜鸟教程!"

Character 方法

序号方法与描述
1isLetter() 是否是一个字母
2isDigit() 是否是一个数字字符
3isWhitespace() 是否是一个空白字符
4isUpperCase() 是否是大写字母
5isLowerCase() 是否是小写字母
6toUpperCase() 指定字母的大写形式
7toLowerCase() 指定字母的小写形式
8toString() 返回字符的字符串形式,字符串的长度仅为1