# 常用API

# Math

Math类中包含许多有关数学计算的方法。

方法 描述
public static int abs(int x) 返回x的绝对值
public static double ceil(double x) 向上取整
public static double floor(double x) 向下取整
public static int max(int x, int y) 返回两个数中的较大值
public static int min(int x, int y) 返回两个数中的较小值
public static double pow(double x, double y) 返回x的y次方
public static double random() 返回0.0到1.0之间的随机数(不包含1.0)
public static int round(double x) 返回x四舍五入后的整数

# abs 向上取整

package api;

public class MathText {
    public static void main(String[] args) {
        // abs 返回参数绝对值
        //整数
        System.out.println(Math.abs(-1));//1
        System.out.println(Math.abs(1));//1
        //小数
        System.out.println(Math.abs(-1.1));//1,1
        System.out.println(Math.abs(1.1));//1,1
    }
}

注意

abs bug

  • 以int类型为例,取值范围为 -2147483648 到 2147483647,
  • 如果没有正数与负数对应,那么传递负数结果有误
  • -2147483648m没有正数对应 所以abs结果产生bug
    System.out.println(Math.abs(-2147483648));//-2147483648 System.out.println(Math.absExact(2147483647));//报错

# ceil 向上取整 和 floor 向下取整

package api;

public class Cell {
    public static void main(String[] args) {
        //向上取整
        System.out.println(Math.ceil(1.0));//1.0
        System.out.println(Math.ceil(1.1));//2.0
        System.out.println(Math.ceil(12.34));//13.0
        System.out.println(Math.ceil(-12.34));//-12.0
        //向下取整
        System.out.println(Math.floor(1.0));//1.0
        System.out.println(Math.floor(1.1));//1.0
        System.out.println(Math.floor(12.34));//12.0
        System.out.println(Math.floor(-12.34));//-13.0
    }
}

# round 四舍五入

package api;

public class Round {
    public static void main(String[] args) {
        System.out.println(Math.round(1.8));//2
        System.out.println(Math.round(-1.8));//-2
        System.out.println(Math.round(1.5));//2
        System.out.println(Math.round(-1.5));//-1
        System.out.println(Math.round(1.3));//1
        System.out.println(Math.round(-1.3));//-1
    }
}

注意

round四舍五入负数时,如果小数位为0.5 则向上取整

# max min 返回两个数中的较大值和较小值

package api;

public class MaxMin {
    public static void main(String[] args) {
        //如果输入的参数类型不同,则返回较大值类型
        System.out.println(Math.max(1.1, 3));//3.0
        System.out.println(Math.min(1.1, 3));//1.1
    }
}

注意

如果输入的参数类型不同,则返回较大值类型

# pow 返回x的y次方

package api;

public class Pow {
    public static void main(String[] args) {
        System.out.println(Math.pow(2, 3));//8.0
        System.out.println(Math.pow(2, -2));//0.25
    }
}

注意

  • pow返回值类型为double
  • pow的第二个参数建议为大于1的整数

# System

是一个工具类,它提供了一些与系统相关的操作方法。

方法 描述
public static void exit(int status)
终止当前运行的java虚拟机
public static long currentTimeMillis() 返回当前系统的时间戳
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) 克隆数组

# exit

public class Syatem {
    public static void main(String[] args) {
        //终止程序
        //status 0 正常结束 1 程序异常结束
        System.exit(1);
    }
}

# currentTimeMillis

public class CurrentTimeMillis {
    public static void main(String[] args) {
        System.out.println(System.currentTimeMillis());
    }
}

currentTimeMillis返回的是当前系统的时间戳,单位是毫秒。

# arraycopy

  • 参数一:数据源要拷贝的数据从何而来
  • 参数二:数据源中拷贝数据的起始位置
  • 参数三:拷贝到目标数组
  • 参数四:目标数组中拷贝数据的起始位置
  • 参数五:拷贝数据的个数
public class ArrayCopy {
    public static void main(String[] args) {
        //数组拷贝
        int[] arr = {1, 2, 3, 4, 5};
        int[] arr2 = new int[arr.length];
        //把arr数组中的数据拷贝到arr2数组中
        //参数一:数据源要拷贝的数据从何而来
        //参数二:数据源中拷贝数据的起始位置
        //参数三:拷贝到目标数组
        //参数四:目标数组中拷贝数据的起始位置
        //参数五:拷贝数据的个数
        System.arraycopy(arr, 0, arr2, 0, arr.length);
        for (int i : arr2) System.out.print(i + " ");//1 2 3 4 5
    }
}

注意

  1. 如果数据源数组和目的地数组都是基础数据类型,那么两者的类型必须保持一致,否则会报错
public class ArrayCopy {
    public static void main(String[] args) {
        int[] arr3 = {1, 2, 3, 4, 5};
        double[] arr4 = new double[arr3.length];
        System.arraycopy(arr3, 0, arr4, 0, arr3.length);
    }
}
  1. 在拷贝的时候需要考虑数组的长度,如果超出范围就会报错
public class ArrayCopy {
    public static void main(String[] args) {
        int[] arr3 = {1, 2, 3, 4, 5};
        int[] arr4 = new int[2];
        System.arraycopy(arr3, 0, arr4, 0, 6);

    }
}
  1. 如果数据源数组和目的地数组都是引用类型,那么子类类型可以赋值给父类类型
public class ArrayCopy {
    public static void main(String[] args) {
        Test person1 = new Test("张三", 18);
        Test person2 = new Test("李四", 20);
        Test[] arr3 = {person1, person2};
        Person[] arr4 = new Person[arr3.length];
        //把arr3数组中的数据拷贝到arr4数组中
        System.arraycopy(arr3, 0, arr4, 0, arr3.length);
    }
}

# Runtime

表示当前虚拟机的运行环境

方法 描述
public static Runtime getRuntime() 返回当前虚拟机的运行环境
public void exit(int status) 终止当前虚拟机
public int availableProcessors() 获取获得的cpu线程数
public long maxMemory() Jvm能从系统中获取总内存大小(单位byte)
public long totalMemory() Jvm已从系统中获取的总内存大小(单位byte)
public long freeMemory() Jvm剩余内存大小(单位byte)
package api;

import java.io.IOException;

public class RuntimeText {
    public static void main(String[] args) throws IOException {
        //返回当前虚拟机的运行环境
        Runtime runtime = Runtime.getRuntime();
//        System.out.println("终止当前虚拟机");
//        runtime.exit(1);
        System.out.println("获取获得的cpu线程数" + runtime.availableProcessors());
        System.out.println("Jvm能从系统中获取总内存大小" + runtime.maxMemory() / 1024 / 1024 / 1024 + "G");
        System.out.println("Jvm已从系统中获取的总内存大小" + runtime.totalMemory() / 1024 / 1024 + "M");
        System.out.println("Jvm剩余内存大小" + runtime.freeMemory() / 1024 / 1024 + "M");
        //使用cmd命令打开记事本
        runtime.exec("notepad");
        //shotdown : 关机
        //该cmd命令必须加上参数才可运行
        //-s:默认在一分钟之后关机
        //-s -t:指定时间:指定关机时间
        //-a 取消关机操作
        //-r :重启
        runtime.exec("shutdown -s -t 3600");
        runtime.exec("shutdown -a");

    }

}

# Object

  • Object是所有类的父类,所有类都直接或间接继承自Object
  • toString一般会重写,打印对象时打印属性
  • equals一般会重写,比较对象的属性值是否相等
  • clone默认浅克隆,如果需要深克隆,需要重写方法,或者使用的三方克隆工具类
方法 描述
public String toString() 返回对象的字符串表示形式
public boolean equals(Object obj) 判断两个对象是否相等
public int hashCode() 返回对象的哈希码值

# toString

public class ToString {
    public static void main(String[] args) {
        Object obj = new Object();
        //返回对象的字符串表示形式
        System.out.println(obj.toString());//java.lang.Object@10f87f48

        // System.out.println()方法细节
        //system:类名
        //out:静态变量
        //system.out:获取打印对象
        //println():方法名
        //参数:表示打印内容
        //核心逻辑
        //当我们打印一个对象的时候,底层会调用对象的toString方法返回的是地址值
        //所以:默认情况下,打印一个对象打印的就是地址值
        //解决方法重写类中的toString方法
    }
}

# equals

public class Equals {
    public static void main(String[] args) {
        //判断两个对象是否相等
        Object obj1 = new Object();
        Object obj2 = new Object();
        System.out.println("判断两个对象是否相等" + obj1.equals(obj2));//false

        //比较属性值 重写类中的equals方法
        PersonApi p1 = new PersonApi("张三", 18);
        PersonApi p2 = new PersonApi("张三", 18);
        System.out.println("判断两个对象是否相等" + p1.equals(p2));//true

    }
}

class PersonApi {
    String name;
    int age;

    public PersonApi(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        PersonApi person = (PersonApi) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

# clone 对象克隆

package api;

public class CloneText {
    public static void main(String[] args) throws CloneNotSupportedException {
        clonePerson p1 = new clonePerson("张三", 18);
        clonePerson cloneText = (clonePerson) p1.clone();
        System.out.println(p1);//clonePerson{name='张三', age=18}
        System.out.println(cloneText);//clonePerson{name='张三', age=18}
    }
}

class clonePerson implements Cloneable {
    String name;
    int age;

    //重写toString方法
    @Override
    public String toString() {
        return "clonePerson{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public clonePerson(String name, int age) {
        this.name = name;
        this.age = age;
    }

    protected Object clone() throws CloneNotSupportedException {
        //调用父类的clone方法
        //相当于让java帮我们克隆一个对象,并把克隆之后的对象返回出去
        return super.clone();
    }
}

  • 浅克隆:不管对象内部的属性是基本数据类型还是引用数据类型,都完全拷贝过来
  • 深克隆:基本数据类型拷贝过来,字符串复用串池中的,引用数据类型会重新创建新的

# Objects

Objects中的成员方法

方法 描述
public static boolean equals(Object a, Object b) 判断两个对象是否相等
public static boolean isNull(Object obj) 判断对象是否为null,为null返回true,否则返回false
public static boolean nonNull(Object obj) 判断对象是否为null,结果与isNull相反

# equals 对象比较

public class ObjectsText {
    public static void main(String[] args) {
        //objects
        clonePerson p3 = null;

        clonePerson p4 = new clonePerson("王五", 20);
        //判断两个值是否相同
        boolean result = Objects.equals(p3, p4);
        //细节
        //1.方法的底层会判断p3和p4是否为null 如果有其中一个为null则直接返回false
        //2. 如果p3不为null 则就利用p3再次调用equals方法
        //3. 此时p3是clonePerson类型的 因此最终还是会调用clonePerson的equals方法
        //如果没有重写equals方法 则比较地址值,如果重写了 就按照重写的方式比较
        System.out.println(result);//false
    }
}

class clonePerson implements Cloneable {
    String name;
    int age;
    int[] arr = {1, 2, 3};

    @Override
    public String toString() {
        return "clonePerson{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", arr=" + Arrays.toString(arr) +
                '}';
    }

    public clonePerson(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int[] getArr() {
        return arr;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        System.out.println("equals方法执行");
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        clonePerson that = (clonePerson) o;
        return age == that.age && Objects.equals(name, that.name) && Objects.deepEquals(arr, that.arr);
    }


    protected Object clone() throws CloneNotSupportedException {
        System.out.println("克隆方法执行");
        //深克隆的实现
        int[] arr = new int[this.arr.length];
        //复制数组
        System.arraycopy(this.arr, 0, arr, 0, this.arr.length);
        //调用父类的clone方法
        //相当于让java帮我们克隆一个对象,并把克隆之后的对象返回出去
        clonePerson u = (clonePerson) super.clone();
        u.arr = arr;
        return u;
    }
}

# isNullnonNull

isNullnonNull都是Objects中的静态方法,用于判断对象是否为nullnonNull的结果与isNull相反`

public class ObjectsText {
    public static void main(String[] args) {
        //isNull与nonNull
        clonePerson p5 = null;
        //判断一个值是否为null
        System.out.println(Objects.isNull(p5));//true

        //nonNull的结果与isNull相反
        System.out.println(Objects.nonNull(p5));//false
    }
}

# BigInteger

BigInteger类用于表示大整数,它实现了java.lang.Comparable接口,因此可以比较大小,并且提供了一些数学运算的方法。

方法 描述
public static BigInteger valueOf(long val) 返回一个BigInteger对象,内部有优化
public BigInteger(int num,Random rnd) 获取随机大整数,范围:[0~ 2的num次方-1]
public BigInteger(Sting val) 获取指定的大整数
public BigInteger(String val,int radix ) 获取指定进制的大整数

# 获取随机大整数

public BigInteger(int num,Random rnd) 可获取随机大整数,范围:[0~ 2的num次方-1]

public class BigIntegerText {
    public static void main(String[] args) {
        //获取一个随机的大整数
        Random random = new Random();
        BigInteger bigInteger = new BigInteger(4, random);//0~ 2^4 -1
        System.out.println("获取随机大整数  " + bigInteger);//(0~15]

    }
}

# 获取指定的大整数

public BigInteger(Sting val) 获取指定的大整数

public class BigIntegerText {
    public static void main(String[] args) {
        BigInteger bigInteger1 = new BigInteger("100");
        System.out.println("获取指定的大整数  " + bigInteger1);

//        BigInteger bigInteger2 = new BigInteger("abc|1.1");//报错 数字格式化错误

    }
}

细节

  • 字符串中的数字必须是整数
  • 字符串中的进制必须跟进制吻合
  • 比如二进制中只能写0和1,否则报错
public class BigIntegerText {
    public static void main(String[] args) {
        BigInteger bigInteger2 = new BigInteger("100", 16);//表示将16进制的100转为10进制
        System.out.println("获取指定进制的大整数  " + bigInteger2);//256
    }
}

# 静态方法获取BigInteger的对象

public static BigInteger valueOf(long val) 返回一个BigInteger对象,内部有优化

public class BigIntegerText {
    public static void main(String[] args) {
        BigInteger bigInteger3 = BigInteger.valueOf(100);
        System.out.println("静态方法获取BigInteger的对象  " + bigInteger3);
    }
}

# 细节1

valueOf静态方法能表示的范围比较小,在long的取值范围之内,如果超过long的取值范围就会报错

public class BigIntegerText {
    public static void main(String[] args) {
        //获取long类型的最大取值
        System.out.println("long的最大取值范围" + Long.MAX_VALUE);
        BigInteger bigInteger4 = BigInteger.valueOf(9223372036854775807L);//L表示是Long类型
        BigInteger bigInteger5 = BigInteger.valueOf(9223372036854775808L);//报错
        System.out.println("静态方法获取BigInteger的对象(最大取值范围)  " + bigInteger4);
    }
}

# 细节2

  • valueOf在内部把常用的数字进行了优化
  • 提前把-16~16 先创建好BigInteger对象,如果多次获取不会创建新的对象
public class BigIntegerText {
    public static void main(String[] args) {
        BigInteger bigInteger5 = BigInteger.valueOf(16);
        BigInteger bigInteger6 = BigInteger.valueOf(16);
        System.out.println(bigInteger5 == bigInteger6);//比较地址值 true

        BigInteger bigInteger7 = BigInteger.valueOf(17);
        BigInteger bigInteger8 = BigInteger.valueOf(17);
        System.out.println(bigInteger7 == bigInteger8);//false
    }
}

# 细节3

对象一但创建内部的数据不会发生改变

public class BigIntegerText {
    public static void main(String[] args) {
        BigInteger bigInteger9 = BigInteger.valueOf(1);
        BigInteger bigInteger10 = BigInteger.valueOf(2);
        BigInteger result = bigInteger9.add(bigInteger10);
        System.out.println("对象一但创建内部的数据不会发生改变  " + result);//3
        System.out.println(result == bigInteger9);//false
        System.out.println(result == bigInteger10);//false
    }
}

# BigInteger构造方法小结

  • 如果BigInterger表示的数字没有超出long的取值范围,可以用静态方法获取BigInteger.valueOf()
  • 如果BigInterger表示的数字超出了long的取值范围,可以用构造方法获取new BigInteger("100")
  • 对象一但创建BigInteger内部的数据不会发生改变
  • 只要进行计算都会产生一个新的BigInteger对象

# BigInteger常见的成员方法

方法 描述
public BigInteger add(BigInteger val) 加法
public BigInteger subtract(BigInteger val) 减法
public BigInteger multiply(BigInteger val) 乘法
public BigInteger divide(BigInteger val) 除法
public BigInteger[] divideAndRemainder(BigInteger val) 除法,获取商和余数
public boolean equals(Object val) 判断是否相等
public BigInteger pow(int num) 指数运算
public BigInteger mod(BigInteger val) 求余数
public BigInteger max/min (BigInteger val) 返回较大值/较小值
public int intValue(BigInteger val) 转为int类型的整数,超出范围数据有误

# add加法

public BigInteger add(BigInteger val) 加法

public class BigIntegerText {
    public static void main(String[] args) {
        BigInteger bigInteger11 = BigInteger.valueOf(1);
        BigInteger bigInteger12 = BigInteger.valueOf(2);
        BigInteger result1 = bigInteger11.add(bigInteger12);
        System.out.println("加法运算  " + result1);//3
    }
}

# divideAndRemainder除法 获取商和余数

public class BigIntegerText {
    public static void main(String[] args) {
        //除法 获取商和余数
        BigInteger bigInteger13 = BigInteger.valueOf(200);
        BigInteger bigInteger14 = BigInteger.valueOf(3);
        BigInteger[] result2 = bigInteger13.divideAndRemainder(bigInteger14);
        System.out.println("除法 获取商和余数  商" + result2[0] + "余数" + result2[1]);//商66余数2
    }
}

# equals比较是否相同

public class BigIntegerText {
    public static void main(String[] args) {
        BigInteger bigInteger15 = BigInteger.valueOf(200);
        BigInteger bigInteger16 = BigInteger.valueOf(20);
        System.out.println("比较是否相同  " + bigInteger15.equals(bigInteger16));//false
    }
}

# pow指数运算

public class BigIntegerText {
    public static void main(String[] args) {
        BigInteger bigInteger17 = BigInteger.valueOf(2);
        BigInteger result3 = bigInteger17.pow(3);
        System.out.println("次幂运算  " + result3);//8
    }
}

# min/max返回较大值、较小值

public class BigIntegerText {
    public static void main(String[] args) {
        BigInteger bigInteger18 = BigInteger.valueOf(2);
        BigInteger bigInteger19 = BigInteger.valueOf(3);
        System.out.println("返回较大值、较小值  " + bigInteger18.max(bigInteger19));//3
        System.out.println("返回较大值、较小值  " + bigInteger18.min(bigInteger19));//2
    }
}

# intValue转为int类型的整数

public class BigIntegerText {
    public static void main(String[] args) {
        //转为int类型的整数 超出范围数据有误
        BigInteger bigInteger20 = BigInteger.valueOf(200);
        int result4 = bigInteger20.intValue();
        System.out.println("转为int类型的整数  " + result4);//200

    }
}

注意

转为int类型的整数 超出范围数据有误

public class BigIntegerText {
    public static void main(String[] args) {
        BigInteger bigInteger20 = BigInteger.valueOf(200);
        int result4 = bigInteger20.intValue();
        System.out.println("转为int类型的整数  " + result4);//-2147483648
    }
}

# BigDecima的基本使用

# BigDecimal作用

  • 用于小数的精确计算
  • 可以用来表示很大的小数

# 用法

package api;

import java.math.BigDecimal;

public class BigDecimaText {
    public static void main(String[] args) {
        System.out.println(0.09 + 0.01);
        System.out.println(0.216 - 0.1);
        System.out.println(0.226 * 0.01);
        System.out.println(0.09 / 0.1);

        //创建一个bigdecimal对象
        //1。通过传递一个double类型的小数来创建对象
        //这种方法有可能是不精确的,所以不建议使用
        BigDecimal bi = new BigDecimal(0.01);//0.01000000000000000020816681711721685132943093776702880859375
        BigDecimal b2 = new BigDecimal(0.09);//0.0899999999999999966693309261245303787291049957275390625
        System.out.println(bi);
        System.out.println(b2);

        //通过传递字符串表示的小数来创建对象
        BigDecimal b3 = new BigDecimal("0.01");//0.01
        BigDecimal b4 = new BigDecimal("0.09");//0.09
        System.out.println(b3);
        System.out.println(b4);

        //此类的加法操作
        BigDecimal b5 = b3.add(b4);
        System.out.println(b5);//0.10

        //通过静态方法获取对象
        BigDecimal b6 = BigDecimal.valueOf(0.01);
        BigDecimal b7 = BigDecimal.valueOf(0.09);
        System.out.println(b6);
        System.out.println(b7);
        //细节
        //1.如果要表示的数字不大,没有超出double的取值范围,建议使用静态方法
        //2.如果要表示的数字比较大,超出的double的取值范围,建议使用静态方法
        //3.如果我们传递的是0~10之间的整数包含0、包含10,那么方法会返回已经创建好的对象,不会重新new
    }
}

# 成员方法

方法名 作用
public static BigDecimal valueOf(double val)
public BigDecimal add(BigDecimal val) 加法
public BigDecimal subtract(BigDecimal val) 减法
public BigDecimal multiply(BigDecimal val) 乘法
public BigDecimal divide(BigDecimal val) 除法
public BigDecimal divide(BigDecimal val,int scale(精确几位),int roundingMode(舍入模式)) 除法

# 数学计算

package api;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class BigDecimalText {
    public static void main(String[] args) {
        //BigDecimal 数学运算

        //静态方法获取对象
        BigDecimal big1 = BigDecimal.valueOf(1.1);
        BigDecimal big2 = BigDecimal.valueOf(2.1);
        //加法 big1+big2
        BigDecimal big3 = big1.add(big2);
        System.out.println(big3);//3.2
        //减法 big1-big2
        BigDecimal big4 = big1.subtract(big2);
        System.out.println(big4);//-1.0
        //乘法 big1*big2
        BigDecimal big5 = big1.multiply(big2);
        System.out.println(big5);//2.31
        //除法 big1/big2
        BigDecimal big6 = big1.divide(big2, 10, RoundingMode.DOWN);
        System.out.println(big6);//0.5238095238
    }
}

注意

使用BigDecimal进行除法运算时,如果遇到除不尽的小数在不指定精确位数和舍入模式时,会抛出ArithmeticException异常

# 正则表达式

  • 正则表达式可以校验字符串是否满足一定的规则,并用来校验数据格式的合法性
  • 在一段文本中查找想要的内容

# 字符类(只匹配一个字符)

字符类 说明
[abc] 只能是a、b、c中的任意一个字符
[^abc] 除了a、b、c中的任意一个字符
[a-zA-z] 只能是a~z或A-Z中的任意一个字符
[a-d[m-p]] a~d或m~p中的任意一个字符
[a-z&&[def]] a~z和d、e、f的交集 为:d,e,f
[a-z&&[^bc]] a~z和非b、c的交集 为:等同于[ad-z]
[a-z&&[^m-p]] a~z和非m~p的交集 为:等同于[a-lq-z]
package api;

public class regularText {
    public static void main(String[] args) {
        //正则表达式
        System.out.println("-------------------1------------------");
        //只能是a或b或c
        System.out.println("a".matches("[abc]"));//true
        System.out.println("d".matches("[abc]"));//false
        System.out.println("aa".matches("[abc]"));//false
        //注意 字符类正则只能匹配一个字符,如需匹配多个需要再写一个字符类正则
        System.out.println("aa".matches("[abc][abc]"));//true

        System.out.println("-------------------2------------------");
        //不能出现a,b,c
        System.out.println("a".matches("[^abc]"));//false
        System.out.println("d".matches("[^abc]"));//true
        System.out.println("aa".matches("[^abc]"));//false
        //注意 字符类正则只能匹配一个字符,如需匹配多个需要再写一个字符类正则
        System.out.println("aa".matches("[^abc][^abc]"));//true


        System.out.println("-------------------3------------------");
        //a-z A-Z (包括头尾范围)[a-d[m-p]]相同作用
        System.out.println("a".matches("[a-zA-Z]"));//true
        System.out.println("AA".matches("[a-zA-Z]"));//false
        System.out.println("1".matches("[a-zA-Z]"));//false

        System.out.println("-------------------4------------------");
        //a-z与def交集 (包括头尾范围)
        System.out.println("a".matches("[a-d&&[def]]"));//false
        System.out.println("d".matches("[a-d&&[def]]"));//true
        System.out.println("0".matches("[a-d&&[def]]"));//false
        //注意 如果要求两个范围的交集那么需要写符号&&
        //如果只写一个符号那么就是一个简简单单的&符号
        System.out.println("&".matches("[a-d&&[def]]"));//false
        System.out.println("&".matches("[a-d&[def]]"));//true

        System.out.println("-------------------5------------------");
        //a-z与非bc交集 (包括头尾范围)等同于[ad-z]
        System.out.println("a".matches("[a-z&&[^bc]]"));//true
        System.out.println("a".matches("[ad-z]"));//true
        System.out.println("0".matches("[a-z&&[^bc]]"));//false


        System.out.println("-------------------6------------------");
        //a-z与非m-p的交集 (包括头尾范围)等同于[a-lq-z]
        System.out.println("a".matches("[a-z&&[^m-p]]"));//true
        System.out.println("a".matches("[a-lq-z]"));//true
        System.out.println("0".matches("[a-z&&[^m-p]]"));//false
    }
}

# 预定义字符(只匹配一个字符)

预定义字符 说明
. 任何字符
\d 一个数字:[0-9]
\D 非数字:[^0-9]
\s 一个空白字符:[\t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 一个单词字符(英文、数字、下划线):[a-zA-Z_0-9]
\W 一个非单词字符:[^\w]

注意

  • \是转义字符,改变后面字符原本的含义
  • 例,以字符串的形式打印一个双引号
  • System.out.println("\"");
  • 此时\的作用是转义双引号,转义后的字符串为:"\""
package api;

public class regularText {
    public static void main(String[] args) {
        System.out.println("-------------------1------------------");
        //. 表示任意一个字符(只能匹配一个字符)
        System.out.println("a".matches("."));//true
        System.out.println("你".matches("."));//true
        System.out.println(" ".matches("."));//true
        System.out.println("".matches("."));//false
        //注意: 预定义字符也是只能匹配一个字符
        System.out.println("aa".matches("."));//false

        System.out.println("-------------------2------------------");
        //\d 表示数字(0-9)  \\表示一个字符串的\
        System.out.println("1".matches("\\d"));//true
        System.out.println("a".matches("\\d"));//false
        System.out.println(" ".matches("\\d"));//false
        System.out.println("33".matches("\\d"));//false

        System.out.println("-------------------3------------------");
        //\w只能是一位单词字符 (a-zA-Z0-9_)
        System.out.println("a".matches("\\w"));//true
        System.out.println("A".matches("\\w"));//true
        System.out.println("0".matches("\\w"));//true
        System.out.println("_".matches("\\w"));//true
        System.out.println("你".matches("\\w"));//false

        //以上正则表达式只能校验单个字符
        System.out.println("-------------------4------------------");
        //必须是字母下划线至少六位
        System.out.println("abcdef".matches("\\w{6}"));//true
        System.out.println("abcdefg".matches("\\w{6}"));//false
        System.out.println("abcdefg".matches("\\w{6}g"));//false
    }
}

# 数量词

数量词 说明
X? X,零次或多次
X* X,零次或多次
* 零个或多个
X+ X,一次或多次
X{n} X,n次
X{n,} X,至少n次
X{n,m} X,至少n次,至多m次

# 正则表达式练习

心得:拿着一个正确的数据,从左到右依次编写

# 手机号验证

17687005862

# 思路:分成三部分

  • 一:1表示手机号码只能以1开头
  • 二:3-9 表示手机号码的第二位只能是3-9之间
  • 三:\d{9}表示从第三位开始任意数字可以出现9次 且只能出现9次
package api;

public class regularText {
    public static void main(String[] args) {
        String phone = "1[3-9]\\d{9}";
        System.out.println("17687005862".matches(phone));//true
        System.out.println("176870058".matches(phone));//false
    }
}

# 座机号码验证

020-2324242 02122442 0712-3242434

# 思路:在书写座机号的时候需要把正确的数据分为三部分

  • 一:区号一定是一0开头 从第二位开始可以是任意的一位数字,可以出现2-3次
  • 二:- 可以出现1次也可以出现0次(?表示可以出现0次或者1次)
  • 三:号码,号码的第一位也不能以0开头,从第二位开始可以是任意的数字,号码的总长度5-8位
package api;

public class regularText {
    public static void main(String[] args) {
        //验证座机
        String phone2 = "0\\d{2,3}-?[1-9]\\d{4,9}";
        System.out.println("020-2324242".matches(phone2));//true
        System.out.println("02122442".matches(phone2));//true
        System.out.println("0712-3242434".matches(phone2));//true
    }
}

# 邮箱号验证

1450432546@qq.com 3232323@pic.com.cn zhangsan@163.com

# 思路:把正确的数据分为三部分

  • 第一部分:@的左边任意字符至少出现一次
  • 第二部分:@ 一定出现一次 @
  • 第三部分:@的右边
  1. .的左边 [\\w&&[^_]]{2,6}任意的字母加数字(且不能出现下划线)
  2. \\.一定出现. 且只出现一次
  3. 大写字母。小写字母都可以只能出现2-3次 [a-zA-Z]{2,3}
  4. (\\.[a-zA-Z]{2,3}){1,2}小括号的的数据为一组 表示这一组可以出现1-2次
package api;

public class regularText {
    public static void main(String[] args) {
        //验证邮箱
        //1450432546@qq.com 3232323@pic.com.cn zhangsan@163.com
        String email = "\\w+@[\\w&&[^_]]{2,6}(\\.[a-zA-Z]{2,3}){1,2}";
        System.out.println("1450432546@qq.com".matches(email));//true
        System.out.println("3232323@pic.com.cn".matches(email));//true
        System.out.println("zhangsan@163.com".matches(email));//true
    }
}

# 思路:分成3部分来写

  • @的左边 可以是任意的数字、字母、下划线,可以出现任意次 至少出现一次 \w
  • @ 一定出现一次 @
  • @的右边
  1. 在.左边qq.com pic.com.cn 163.com可以去除下划线的任意的数字、字母,可以出现任意次 至少出现一次 \w&&[^_]

# 用户名验证

要求:大小写字母、数字、下划线一共4-16位 \\w{4,16}

# 身份证号码的简单校验

[1-9]\\d{16}(\\d|x|X)[1-9]\\d{16}[\\dXx]

# 忽略大小写的书写方式

  • 忽略abc的大小写(?i)abc
  • 忽略bc的大小写a(?i)bc
  • 忽略b的大小写a((?i)b)c
package api;

public class regularText {
    public static void main(String[] args) {
        String regex = "(?i)abc";
        System.out.println("abc".matches(regex));//true
        System.out.println("ABC".matches(regex));//true
        System.out.println("Abc".matches(regex));//true
        System.out.println("aBc".matches(regex));//true
    }
}

# 身份证号码的严格校验

530122199907310014

  • 前面六位:省份、市区、派出所等信息:第一位不能是0,后面5位可以是任意数字
  • 年份:年的前半段:18、19、20 年的后半段:任意数字出现两次
  • 月份:01~09 10 11 12
  • 日期: 01-31
  • 后面四位:任意数字出现3次 最后一位可以是X或者x
package api;

public class regular {
    public static void main(String[] args) {
        String idCard = "[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(1[1-9]|[1-2][0-9]|3[01])\\d{3}((?i)x|\\d)";
        System.out.println("53012219990731001x".matches(idCard));//true
        System.out.println("530122199907310014".matches(idCard));//true
    }
}

# 使用正则查找内容

  • Pattern类:表示正则表达式
  • Matcher类:文本匹配器,作用按照正则表达式的规则去读取字符串 从头开始读取,在大串中年去找符合匹配规则的子串
public class regular {
    public static void main(String[] args) {
        //获取正则表达式的对象
        Pattern pattern = Pattern.compile("java\\d{0,2}");
        //获取文本匹配器的对象
        //matcher 文本匹配器的对象
        //str 大串
        //pattern 匹配文本规则
        //matcher 要在str中找符合p规则的小串
        Matcher matcher = pattern.matcher("java11java22java33");
        while (matcher.find()) {
            //拿着文本匹配器从头开始读取,寻找是否有满足规则的小串
            //如果有find()方法就返回true,在底层记录子串的起始索引和结束索引+1,没有就返回false

            //方法底层会根据find方法记录的索引进行字符串的截取
            //substring(start,end) 包头不包尾
            //会把截取的小串进行返回
            String substring = matcher.group();
            System.out.println(substring);

            //在第二次调用find()方法时,会继续读取后面的内容
            //读取到第二个满足要求的子串,方法会继续返回true
            //并把第二个子串的起始索引和结束索引+1进行记录
        }
    }
}

# 使用正则进行网络爬取

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class regular {
    public static void main(String[] args) throws IOException {
        package api;
        public class crawler {
            public static void main(String[] args) throws IOException {
                //https://tmxkj.top/#/site
                //将该网站的链接全部爬取出来
                URL url = new URL("https://myarticle.tmxkj.top/Article/Back/Java/");

                //链接上该网址
                URLConnection conn = url.openConnection();

                //创建一个数据去读取网络中的数据
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));

                String line;
                //获取正则表达式的对象
                Pattern p = Pattern.compile("<a href=\"(.*?)\"");
                //在读取的时候每次读一行
                while ((line = br.readLine()) != null) {
                    System.out.println("开始爬取" + line);
                    //拿着文本匹配器的对象matcher按照pattern的规则去读取当前这一行的信息
                    Matcher m = p.matcher(line);
                    while (m.find()) {
                        System.out.println(m.group());
                    }
                }
            }
        }

    }
}

# 有条件的爬取数据

public class crawler {
    public static void main(String[] args) {
        //有条件的爬取数据
        String str = "javajava11java22java33";
        //定义正则表达式的对象
        //?等于前面的java 相当于后面的占位
        //= 表示在java后面要跟随的数据
        //:表示获取整体所有的东西
        //但是在获取的时候只获取前半部分
        String rex = "((?i)java)(?=8|11|22)";

        //j忽略大小写
//        String rex = "((?i)java)(?=8|11|22)";
        //获取整体
//        String rex = "((?i)java)(?:8|11|22)";
        //获取除了8|11|22的数据
//        String rex = "((?i)java)(?!8|11|22)";
        //创建正则表达式的对象
        Pattern pattern = Pattern.compile(rex);
        //定义爬取的对象
        Matcher matcher = pattern.matcher(str);
        while (matcher.find()) {
            String substring = matcher.group();
            System.out.println(substring);
        }
    }
}
}

# 贪婪爬取和非贪婪爬取

  • 贪婪爬取:在爬取数据的时候尽可能多的获取数据
  • 非贪婪爬取:在爬取数据的时候尽可能少的获取数据

abbbbbbbbbbb
ab+

  • 在java中默认贪婪爬取
  • 如果在数量词+/*的后面加上?号那么此时就是非贪婪爬取
  • 贪婪爬取:获取abbbbbbbbbbb
  • 非贪婪爬取:获取ab

# 正则表达式在字符串方法中的使用

方法名 功能
public String[] matches(String regex) 判断字符串是否完全匹配正则表达式
public String[] split(String regex) 按照正则表达式进行字符串的拆分
public String replaceAll(String regex, String replacement) 按照正则表达式进行字符串的替换
public class regular {
    public static void main(String[] args) {
        //使用正则表达式替换字符串
        String str2 = "javajava11java22java33";
        String rex2 = "((?i)java)(?:8|11|22)";
        String replace = str2.replaceAll(rex2, "hello word");
        System.out.println(replace);//javahello wordhello wordjava33

        //使用正则表达式切割字符串
        String str3 = "javajava11java22java33";
        String[] split = str3.split("((?i)java)(?=8|11|22)");
        for (String s : split) {
            System.out.println(s);
//          java
//          11
//          22java33
        }
    }
}
}

# 捕获分组和非捕获分组

# 捕获分组

  • 在正则表达式中使用()来表示分组
  • 分组序号 以左括号为基准,最左边的是第一组
  • 在正则表达式中后续还要继续使用本组的数据
  • 正则内部使用:\\组号
  • 正则外部使用:$组号
public class regular {
    public static void main(String[] args) {
        //判断的开始字符和结束字符是否一致
        //。:表示任意字符
        // //X(组号) 表示把第X组的数据拿出来再用一次
        String regx = "(.).+\\1";
        System.out.println("abc".matches(regx));//false
        System.out.println("abca".matches(regx));//true
        System.out.println("1231".matches(regx));//true
        System.out.println("--------------可以有多个字符----------------");
        //判断的开始字符和结束字符是否一致?(可以有多个字符)
        String regx2 = "(.+).+\\1";
        System.out.println("abcabcabca".matches(regx2));//true
        System.out.println("aaaabcaa".matches(regx2));//true
        System.out.println("aaaabc".matches(regx2));//false

        System.out.println("--------------开始部分的每个字符也需要一致----------------");
        //判断的开始字符和结束字符是否一致?(开始部分的每个字符也需要一致)
        //*表示可以出现0次或多次
        String regx3 = "((.)\\2*).+\\1";
        System.out.println("abcabcabca".matches(regx3));//false
        System.out.println("aaaabcaa".matches(regx3));//true
        System.out.println("abcabcabc".matches(regx3));//false
    }
}

# 口吃替换

将字符串:我要学学编编编编程程程程程程
替换为:我要学编程

public class regular {
    public static void main(String[] args) {
        String str4 = "我要学学编编编编程程程程程程";
        String result = str4.replaceAll("(.)\\1+", "$1");
        System.out.println(result);//我要学编程
    }
}

# 非捕获分组

分组之后不需要再用本组数据,仅仅是把数据括起来

符号 含义 举例
(?: 正则) 获取所有 Java(?:a | b | c)
(?= 正则) 获取前面部分 Java(?=a | b | c)
(?! 正则) 获取非指定内容的前面部分 Java(?!a | b | c)
public class regular {
    public static void main(String[] args) {
        //非捕获分组
        //特点:不占用组号
        // \\1报错原因:此时分组不占用组号
        //(?:) (?=) (?!) 都属于非捕获分组
        String rex = "1\\d(?=1|5|6)\\1";
        System.out.println("123456".matches(rex));
    }
}

# Date时间类

  • Date类是一个JDK写好的Javabean类,用来描述时间,精确到毫秒
  • 利用空参构造创建的对象,默认表示系统当前时间
  • 利用有参构造创建的对象,表示指定时间
public class DateText {
    public static void main(String[] args) {
        //date时间类
        //创建时间类对象
        Date date = new Date();
        System.out.println(date);//Thu Aug 08 10:28:57 CST 2024

        //创建对象表示一个指定的时间
        Date date1 = new Date(1691200000000L);
        System.out.println(date1);//Sat Aug 05 09:46:40 CST 2023
        //setTime修改时间
        date1.setTime(1691400000000L);
        System.out.println(date1);//Mon Aug 07 17:20:00 CST 2023
        //getTime获取时间的毫秒值
        System.out.println(date1.getTime());//1691400000000


        //打印时间原点一年后的毫秒值
        Date date2 = new Date();
        //设置原点时间
        date2.setTime(0L);
        //设置一年后的毫秒值
        long time = date2.getTime() + 1000L * 60 * 60 * 24 * 365;
        date2.setTime(time);
        System.out.println(date2);//Fri Jan 01 08:00:00 CST 1971
        System.out.println(date2.getTime());//31536000000


        //定义两个时间对象 判断谁在前谁在后
        Random r = new Random();
        Date date3 = new Date(r.nextInt());
        Date date4 = new Date(r.nextInt());
        if (date3.before(date4))
            System.out.println(date3 + "在" + date4 + "之前");
        else if (date3.after(date4))
            System.out.println(date3 + "在" + date4 + "之后");
        else System.out.println(date3 + "与" + date4 + "相等");
    }
}

# SimpleDateFormat格式化时间类

作用

  • 格式化时间
  • 把字符串表示的时间变成Date对象
构造方法 描述
public SimpleDateFormat() 空参构造方法 使用默认格式
public SimpleDateFormat(String pattern) 使用指定格式
常用方法 描述
public String format(Date date) 格式化时间(日期对象=>字符串时间)
public Date parse(String source) 字符串时间=>日期对象
public class SimpleDateFormatText {
    public static void main(String[] args) throws ParseException {
        //使用默认格式格式化时间
        //创建格式化时间对象
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
        //使用对象方法格式化时间
        String date = simpleDateFormat.format(new Date());
        System.out.println(date);//2024/8/8 15:40

        //使用指定格式格式化时间
        //创建格式化时间对象
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy年MM月dd日 a hh时mm分ss秒 EE");
        //使用对象方法格式化时间
        String date1 = simpleDateFormat1.format(new Date());
        System.out.println(date1);//2024年08月08日 下午 03时50分12秒 周四

        //解析字符串
        String date2 = "2024年08月08日 下午 03时50分12秒 周四";
        //创建对象的格式要跟输入的字符串格式一样
        SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy年MM月dd日 a hh时mm分ss秒 EE");
        try {
            Date date3 = simpleDateFormat2.parse(date2);
            System.out.println(date3);//Thu Aug 08 15:50:12 CST 2024
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

# Calendar日历类

  • Calendar类代表了系统当前时间的日历对象,可以单独修改,获取时间中的年、月、日
  • Calendar类是一个抽象类,不能直接创建对象,而是通过子类创建对象 获取Calendar日历类对象的方法:
方法 描述
public static Calendar getInstance() 获取当前日历对象

# Calendar常用方法

方法 描述
public final Date getTime() 获取日期对象
public final Date setTime(Date date) 给日历设置日期对象
public long getTimeInMillis() 获取时间毫秒值
public void setTimeInMillis(long millis) 给日历设置毫秒值
public int get(int field) 获取日历中指定字段的值
public void set(int field, int value) 设置日历中指定字段的值
public void add(int field, int amount) 给日历中指定字段的值加减
package api;

import java.util.Calendar;
import java.util.Date;

public class CalendarText {
    public static void main(String[] args) {
        //获取日历对象
        //细节:Calendar是一个抽象类,不能直接new,而是通过一个静态方法获取到子类对象
        //底层原理
        //会根据系统的不同时区来获取不同的日历对象
        //会把时间中的纪元,年、月、日、时、分、秒、星期,等等的都放到一个数组中

        //细节2
        //月份:0~11 如果获取出来的是0,那么实际上是1月
        //星期:在老外眼里,星期日是一周中的第一天
        //1(星期日)、2(星期一)3(星期二)4(星期三)5(星期四)6(星期五)7(星期六)
        Calendar c = Calendar.getInstance();//当前时间日历
        System.out.println(c);

        //修改日历代表的时间
        Date d = new Date(0L);
        c.setTime(d);
        System.out.println(c);


        //获取日历中某个字段的信息
        //会把时间中的纪元,年、月、日、时、分、秒、星期,等等的都放到一个数组中
        //0 (纪元)、 1 (年)、 2 (月)、 3 (一年中的第几周) 4 (一个月中的第几周) 5 (日期)

        //在java中Calendar类将索引定义为了常量
        int year = c.get(Calendar.YEAR);
        //月份需要+1
        int month = c.get(Calendar.MONTH) + 1;
        int date = c.get(Calendar.DATE);
        int week = c.get(Calendar.DAY_OF_WEEK);
        int year1 = c.get(1);
        //月份需要+1
        int month1 = c.get(2) + 1;
        int date1 = c.get(5);
        int week1 = c.get(7);
        System.out.println(year + "年" + month + "月" + date + "日" + " " + getWeek(week));//1970年1月1日 星期四
        System.out.println(year1 + "年" + month1 + "月" + date1 + "日" + " " + getWeek(week1));//1970年1月1日 星期四

        //修改日历中某个字段的信息
        c.set(Calendar.YEAR, 2020);
        //如果设置的月份太大 则会自动改变年份
        c.set(Calendar.MONTH, 999);
        System.out.println(c.get(Calendar.YEAR) + "年" + (c.get(Calendar.MONTH) + 1) + "月" + c.get(Calendar.DATE) + "日" + " " + getWeek(c.get(Calendar.DAY_OF_WEEK)));//2103年4月1日 星期日


        //调用方法在这个基础上增加一个月
        c.add(Calendar.MONTH, 1);
        System.out.println(c.get(Calendar.YEAR) + "年" + (c.get(Calendar.MONTH) + 1) + "月" + c.get(Calendar.DATE) + "日" + " " + getWeek(c.get(Calendar.DAY_OF_WEEK)));//2103年5月1日 星期二
//amount为负数 则为减去一个月
        c.add(Calendar.MONTH, -1);
        System.out.println(c.get(Calendar.YEAR) + "年" + (c.get(Calendar.MONTH) + 1) + "月" + c.get(Calendar.DATE) + "日" + " " + getWeek(c.get(Calendar.DAY_OF_WEEK)));//2103年4月1日 星期日

    }

    //查表法
    public static String getWeek(int week) {
        //1(星期日)、2(星期一)3(星期二)4(星期三)5(星期四)6(星期五)7(星期六)
        String[] weeks = {"", "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        return weeks[week];
    }
}


# jdk8新增的时间类

  • jdk7中时间的获取和计算十分麻烦,因此出现jdk8
  • jdk8中的时间类对象是不可变的,当去修改时间时会产生一个新的时间类对象

# date类

# ZoneId获取时区

方法 描述
static Set<String> getAvailableZoneIds() 获取所有时区的id
static ZoneId systemDefault() 获取系统默认时区
static ZoneId of(String zoneId) 获取一个指定的时区id
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Set;

public class ZoneIdText {
    public static void main(String[] args) {
        //1.获取所有的时区 getAvailableZoneIds()
        //返回的是一个set对象的集合 不能使用索引
        Set<String> zoneIds = ZoneId.getAvailableZoneIds();
        //打印set对象的长度
        System.out.println(zoneIds.size());//603
        System.out.println(zoneIds);


        //2.获取系统当前的默认时区
        ZoneId systemDefault = ZoneId.systemDefault();
        System.out.println(systemDefault);//Asia/Shanghai


        //3.获取一个指定的时区
        ZoneId zoneId = ZoneId.of("Asia/Shanghai");
        System.out.println(zoneId);//Asia/Shanghai
    }
}

# Instant获取时间戳

方法 描述
static Instant now() 获取当前时间的Instant对象(时间戳)
static Instant ofXxxx(long epochmilli) 根据(秒/毫秒/纳秒)获取一个指定的Instant对象
ZonedDateTime atZone(ZoneId zone) 获取一个指定时区的日期时间对象
boolean isXxxx(Instant otherInstant) 判断系列的方法
Instant minusXxxx(long millisToSubtract) 减去时间系列的方法
Instant plusXxxx(long millisToSubtract) 增加时间系列的方法
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Set;

public class InstantText {
    public static void main(String[] args) {
        //1.获取当前时间的Instant对象(不带时区,如中国需要加8小时)
        Instant instant = Instant.now();
        System.out.println(instant);//2024-08-13T06:38:15.143195900Z

        //2.根据时间的毫秒值获取Instant对象
        Instant instant1 = Instant.ofEpochMilli(0L);
        //获取的是计算机时间原点的时间
        System.out.println(instant1);//1970-01-01T00:00:00Z

        //3.根据时间的秒钟值获取Instant对象
        Instant instant2 = Instant.ofEpochSecond(1L);
        System.out.println(instant2);//1970-01-01T00:00:01Z

        //4.获取当前时间纳秒值(1s+100000000ns)
        Instant instant3 = Instant.ofEpochSecond(1L, 100000000L);
        System.out.println(instant3);//1970-01-01T00:00:01.100Z

        //5.获取一个指定时区的ZonedDateTime对象
        ZoneId zoneId1 = ZoneId.of("Asia/Shanghai");
        ZonedDateTime zonedDateTime = Instant.now().atZone(zoneId1);
        System.out.println(zonedDateTime);//2024-08-13T14:47:36.240457800+08:00[Asia/Shanghai]

        //6.isXxxx()判断
        Instant instant4 = Instant.ofEpochMilli(1L);
        Instant instant5 = Instant.ofEpochMilli(100L);
        //比较两个时间
        //instant4是否在instant5之前
        System.out.println(instant4.isBefore(instant5));//true
        //instant4是否在instant5之后
        System.out.println(instant4.isAfter(instant5));//false
        //instant4是否等于instant5
        System.out.println(instant4.equals(instant5));//false

        //minusXxxx()减去时间的方法
        Instant instant6 = Instant.ofEpochMilli(300L);
        System.out.println(instant6);//1970-01-01T00:00:00.300Z
        Instant instant7 = instant6.minusMillis(100L);
        System.out.println(instant7);//1970-01-01T00:00:00.200Z
    }
}

# ZoneDateTime获取带时区的时间

方法 描述
static ZonedDateTime now() 获取当前时间的ZoneDateTime对象
ZonedDateTime ofXxxx(long epochmilli) 根据(秒/毫秒/纳秒)获取一个指定的ZoneDateTime对象
ZonedDateTime withXxxx(TemporalField field, long newValue) 修改时间系列的方法
ZonedDateTime minusXxxx(long millisToSubtract) 减去时间系列的方法
ZonedDateTime plusXxxx(long millisToSubtract) 增加时间系列的方法
public class ZoneDateTimeText {
    public static void main(String[] args) {
        //1.获取当前时间系统时间 now()
        ZonedDateTime zonedDateTime1 = ZonedDateTime.now();
        System.out.println(zonedDateTime1);//2024-08-13T15:07:13.664025600+08:00[Asia/Shanghai]

        //2.获取指定时区的系统时间 ofInstant()
        //使用Instant时间对象获取指定时区的时间
        ZonedDateTime zonedDateTime2 = ZonedDateTime.ofInstant(Instant.now(), ZoneId.of("America/Marigot"));
        System.out.println(zonedDateTime2);//2024-08-13T03:07:52.120161900-04:00[America/Marigot]
        //使用年月日时分秒获取指定时区的时间
        ZonedDateTime zonedDateTime5 = ZonedDateTime.of(2005, 11, 1,
                1, 14, 5, 12,
                ZoneId.of("America/Marigot"));
        System.out.println(zonedDateTime5);    //2005-11-01T01:14:05.000000012-04:00[America/Marigot]

        //3.修改时间系列 withXxxx()_
        ZonedDateTime zonedDateTime3 = ZonedDateTime.now().withYear(2025);
        System.out.println(zonedDateTime3);//2025-08-13T15:07:13.664025600+0

        //4.减去时间系列的方法
        ZonedDateTime zonedDateTime4 = ZonedDateTime.now().minusYears(1);
        System.out.println(zonedDateTime4);//2023-08-13T15:11:10.640040+08:00[Asia/Shanghai]
    }
}

# DateTimeFormatter日期格式化类

方法 描述
static DateTimeFormatter ofPattern(String pattern) 根据指定的格式获取一个DateTimeFormatter对象
String format(ZonedDateTime) 按照指定方式格式化日期对象
import java.time.Instant;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class DateTimeFormatterText {
    public static void main(String[] args) {
        //1。获取一个日期格式化对象
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        //2.格式化日期对象
        //格式化data对象
        //注意 形参必须是ZonedDateTime对象
        String formatZonedDateTime = dateTimeFormatter.format(Instant.now().atZone(ZoneId.of("Asia/Shanghai")));
        System.out.println(formatZonedDateTime);//2024-08-13 15:48:34
    }
}

# Local日历类

  • LocalDate:年、月、日

  • LocalTime:时、分、秒

  • LocalDateTime:年、月、日、时、分、秒

方法 描述
static LocalDate\LocalTime\LocalDateTime now() 获取当前时间的对象
static LocalDate\LocalTime\LocalDateTime ofXxxx(int xxxx)
根据(年/月/日/时/分/秒)获取一个指定的Local对象
get开头的方法 获取日历中年月日时分秒等信息
isBefore/isAfter(LocalDate\LocalTime\LocalDateTime) 比较两个时间
LocalDate\LocalTime\LocalDateTime withXxxx(TemporalField field, long newValue) 修改时间系列的方法
LocalDate\LocalTime\LocalDateTime plusXxxx(long millisToSubtract) 增加时间系列的方法
public class LocalText {
    public static void main(String[] args) {
        //1.获取当前年月日
        LocalDate localDate = LocalDate.now();
        System.out.println(localDate);//2024-08-13

        //2.获取当前时分秒
        LocalTime localTime = LocalTime.now();
        System.out.println(localTime);//16:03:36.906992300

        //3.获取当前年月日时分秒 并且格式化
        LocalDateTime localDateTime = LocalDateTime.now();
        DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        System.out.println(localDateTime.format(dateTimeFormatter1));//2024-08-13 16:06:12

        //4.获取指定时间的年月日
        LocalDate localDate1 = LocalDate.of(2025, 11, 1);
        System.out.println(localDate1);//2025-11-01

        //获取日历中每个字段的值
        //使用LocalTime对象
        LocalTime localTime1 = LocalTime.of(15, 16, 17);
        System.out.println(localTime1.getHour());//15
        //使用日期对象
        LocalDate localDate2 = LocalDate.of(2025, 11, 1);

        //获取年
        int year = localDate2.getYear();
        System.out.println(year);//2025

        //获取月
        //getMonthValue直接获取
        int month = localDate2.getMonthValue();
        System.out.println(month);//11
        //使用getMonth获取
        Month month1 = localDate2.getMonth();
        System.out.println(month1);//NOVEMBER
        //需要使用getValue获取
        System.out.println(month1.getValue());//11

        //获取日
        int dayOfMonth = localDate2.getDayOfMonth();
        System.out.println(dayOfMonth);//1

        //获取年中的第几天
        int dayOfYear = localDate2.getDayOfYear();
        System.out.println(dayOfYear);//305

        //获取星期
        LocalDate localDate3 = LocalDate.now();
        DayOfWeek dayOfWeek = localDate3.getDayOfWeek();
        System.out.println(dayOfWeek);//TUESDAY
        System.out.println(dayOfWeek.getValue());//2

        //is方法表示判断
        System.out.println(localDate3.isBefore(localDate2));//true
        System.out.println(localDate3.isAfter(localDate2));//false
        System.out.println(localDate3.isEqual(localDate2));//false

        //with方法表示修改
        LocalDate localDate4 = localDate3.withYear(2025);
        System.out.println(localDate4);//2025-08-13

        //minus方法表示减去
        LocalDate localDate5 = localDate4.minusYears(1);
        System.out.println(localDate5);//2024-08-13

        //plus方法表示加上
        LocalDate localDate6 = localDate5.plusYears(1);
        System.out.println(localDate6);//2025-08-13

        //判断今天是否是你生日
        LocalDate localDate7 = LocalDate.of(1999, 7, 31);
        LocalDate localDate8 = LocalDate.now();
        //MonthDay月日对象
        //方法一 指定月日
        MonthDay birMonthDay = MonthDay.of(localDate7.getMonthValue(), localDate7.getDayOfMonth());
        System.out.println(birMonthDay);//--07-31
        //方法二 使用LocalDate对象获取
        MonthDay nowMonthDay = MonthDay.from(localDate8);//--08-13
        System.out.println(nowMonthDay);
    }
}

#LocalDateTime转化成LocalDate或者LocalTime

方法 描述
LocalDateTime.toLocalDate() 将LocalDateTime对象转换为LocalDate对象
LocalDateTime.toLocalTime() 将LocalDateTime对象转换为LocalTime对象

# 时间工具类

  • Duration:计算两个时间之间的差值(秒、纳秒)
  • Period:计算两个日期之间的差值(年、月、日)
  • ChronoUnit:计算两个日期之间的差值(所有单位)`
public class DateUtilsText {
    public static void main(String[] args) {
        //时间间隔工具类
        LocalDateTime localDateTime1 = LocalDateTime.of(2025, 11, 1, 1, 14, 5);
        LocalDateTime nowLocalDateTime = LocalDateTime.now();

        //Duration 计算两个时间之间的差值(秒、纳秒)
        Duration duration = Duration.between(nowLocalDateTime, localDateTime1);
        //获取秒
        long seconds = duration.getSeconds();
        System.out.println(seconds);//38390973
        //获取纳秒
        long nano = duration.getNano();
        System.out.println(nano);//50884200
        //获取时间间隔总天数
        long days1 = duration.toDays();
        System.out.println(days1);//444


        //Period:计算两个日期之间的差值(年、月、日)
        //Period.between()方法形参必须是LocalDate对象
        //第二个参数减第一个参数
        Period period = Period.between(nowLocalDateTime.toLocalDate(), localDateTime1.toLocalDate());
        int years = period.getYears();
        System.out.println(years);//1
        int months = period.getMonths();
        System.out.println(months);//2
        int days = period.getDays();
        System.out.println(days);//19
        System.out.println("总共间隔" + years + "年" + months + "月" + days + "天");

        //获取时间间隔总月份
        long totalMonths = period.toTotalMonths();
        System.out.println(totalMonths);//14


        //ChronoUnit 计算两个日期之间的差值(所有单位)
        System.out.println("相差年数" + ChronoUnit.YEARS.between(nowLocalDateTime, localDateTime1));
        System.out.println("相差月数" + ChronoUnit.MONTHS.between(nowLocalDateTime, localDateTime1));
        System.out.println("相差周数" + ChronoUnit.WEEKS.between(nowLocalDateTime, localDateTime1));
        System.out.println("相差天数" + ChronoUnit.DAYS.between(nowLocalDateTime, localDateTime1));
        System.out.println("相差小时数" + ChronoUnit.HOURS.between(nowLocalDateTime, localDateTime1));
        System.out.println("相差分钟数" + ChronoUnit.MINUTES.between(nowLocalDateTime, localDateTime1));
        System.out.println("相差秒数" + ChronoUnit.SECONDS.between(nowLocalDateTime, localDateTime1));
        System.out.println("相差毫秒数" + ChronoUnit.MILLIS.between(nowLocalDateTime, localDateTime1));
        System.out.println("相差微秒数" + ChronoUnit.MICROS.between(nowLocalDateTime, localDateTime1));
        System.out.println("相差纳秒数" + ChronoUnit.NANOS.between(nowLocalDateTime, localDateTime1));
        System.out.println("相差的半天数" + ChronoUnit.HALF_DAYS.between(nowLocalDateTime, localDateTime1));
        System.out.println("相差的十年数" + ChronoUnit.DECADES.between(nowLocalDateTime, localDateTime1));
        System.out.println("相差的世纪(百年)数" + ChronoUnit.CENTURIES.between(nowLocalDateTime, localDateTime1));
        System.out.println("相差的千年数" + ChronoUnit.MILLENNIA.between(nowLocalDateTime, localDateTime1));
        System.out.println("相差的纪元数" + ChronoUnit.ERAS.between(nowLocalDateTime, localDateTime1));
    }
}

# 包装类

  • 包装类就是基本数据类型的引用类型
  • 在集合中无法存储基本数据类型,只能存储引用数据类型,因此需要把基本数据类型转换为引用数据类型
基本数据类型 包装类
byte Byte
short Short
int Integer
char Character
long Long
float Float
double Double
boolean Boolean

# jdk5以前获取包装类的方式

方法 描述
public Integer(int value) 根据传递的整数创建一个Integer对象
public Integer(String s) 根据传递的字符串创建一个Integer对象
public static Integer valueOf(int i) 根据传递的整数创建一个Integer对象
public static Integer valueOf(String s) 根据传递的字符串创建一个Integer对象
public static Integer valueOf(String s,int radix) 根据传递的字符串和进制创建一个Integer对象
public class WrapperClassText {
    public static void main(String[] args) {
        //1.使用构造方法创建包装类
        Integer i1 = new Integer(1);
        System.out.println(i1);//1
        Integer i2 = new Integer("2");
        System.out.println(i2);//2

        //2.利用静态方法创建包装类
        Integer i3 = Integer.valueOf(3);
        System.out.println(i3);//3
        Integer i4 = Integer.valueOf("4");
        System.out.println(i4);//4
        Integer i5 = Integer.valueOf("5", 16);
        System.out.println(i5);//5

        //3.这两种方式创造包装类的区别
        //两者不同是因为使用了new关键字 每一次new都是创建了一个新的对象
        //两者虽然值相等但地址值不一样
        Integer i6 = new Integer(6);
        Integer i7 = new Integer(6);
        System.out.println(i6 == i7);//false

        //在实际开发中-128~127的数据用得比较多
        //如果每次使用都去new对象,非常消耗内存
        //所以java会提前把1~127的数据创建好对象放入内存中
        //如果要用到就不会创建新的,而是直接获取内存中的
        Integer i8 = Integer.valueOf(128);
        Integer i9 = Integer.valueOf(128);
        System.out.println(i8 == i9);//false

        Integer i10 = Integer.valueOf(127);
        Integer i11 = Integer.valueOf(127);
        System.out.println(i10 == i11);//true

        //在以前包装类如何进行计算
        //1.把包装类的对象进行拆箱,变成基本数据类型
        //2.使用基本数据类型进行计算
        //3.把得到的结果再进行装箱,变成包装类对象
        Integer i12 = Integer.valueOf(1);
        Integer i13 = Integer.valueOf(2);
        Integer i14 = i12.intValue() + i13.intValue();
        Integer i15 = Integer.valueOf(i14);
        System.out.println(i15);
    }
}

# 现在获取包装类的方式

  • 在jdk5以后提出了一个机制,自动装箱和自动拆箱
  • 自动装箱:基本数据类型自动变为其对应的包装类
  • 自动拆箱:把包装类自动变为其对应的基本数据类型
  • 在底层,此时还会去自动调用静态方法valueOf得到一个Integer对象,只不过这个动作不需要我们去操作了
public class WrapperClassText {
    public static void main(String[] args) {
        //自动装箱
        Integer i16 = 1;

        Integer i17 = new Integer(2);
        //自动拆箱
        int i18 = i17;
        System.out.println(i18);

        //在jdk5以后int与Integer可以看做同一个东西,因为在内部可以自动转化
    }
}

# Integer包装类成员方法

方法 描述
public static String toBinaryString(int i) 把整数转换为二进制字符串
public static String toOctalString(int i) 把整数转换为八进制字符串
public static String toHexString(int i) 把整数转换为十六进制字符串
public int intValue() 把包装类转换为整数
public static int parseInt(String s) 把字符串转换为整数
public class WrapperClassText {
    public static void main(String[] args) {

        //Ingeter类的静态方法
        //1.把整数转为二进制
        System.out.println(Integer.toBinaryString(100));
        //2.把整数转为八进制
        System.out.println(Integer.toOctalString(100));
        //3.把整数转为十六进制
        System.out.println(Integer.toHexString(100));
        //4.将字符串类型的整数转化为整数类型的整数
        //java是一种强类型的语言,每种数据在java中都有各自的数据类型
        //在计算的时候如果不是同一种数据类型,是无法直接计算的

        //将字符串的123转为Integer进行计算
        String str = "123";
        System.out.println(str + 1);//1231
        int i = Integer.parseInt(str);
        System.out.println(i + 1);//124


        //键盘录入
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一行数据");
        String str1 = sc.nextLine();
        //sc.next()弊端
        //当我们在使用next、nextInt、nextDouble等方法时,如果遇到空格、回车、制表符的时候程序就停止了
        //键盘录入的是123 123 那么此时只能接收到空格前面的数据
        //我们想要接收一整行数据 就需要调用nextLine方法
        //约定:一但使用键盘录入,一定要使用nextLine方法
        //特点:遇到回车才停止
        System.out.println(str1);

    }
}

# 练习

# 1.键盘录入1~100之间的整数并把数据存储在集合中直到集合中的数据和大于200为止

public class WrapperClassText {
    public static void main(String[] args) {
    }

    public static void scText() {
        //练习
        //1.键盘录入1~100之间的整数并把数据存储在集合中直到集合中的数据和大于200为止
        ArrayList<Integer> list = new ArrayList<>();
        while (true) {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入一个1~100之间的整数");
            String str = sc.nextLine();
            //使用正则表表达式判断是否是数字
            if (!str.matches("\\d+")) {
                System.out.println("输入数据非法");
                continue;
            }
            int num = Integer.parseInt(str);
            if (num >= 1 && num <= 100) {
                list.add(num);
                //遍历集合求和
                int sum = getSum(list);
                if (sum >= 200) break;
            } else System.out.println("输入的数据不在范围内");
        }
    }

    //求和函数
    private static int getSum(ArrayList<Integer> list) {
        int sum = 0;
        for (int item : list) sum += item;
        System.out.println("集合中的数据和为:" + sum);
        return sum;
    }
}

# 自己实现parseInt方法的效果,将字符串形式的数据转换成整数

要求

  1. 字符串中只能是数字不能有其他字符
  2. 至少一位,至多10位
  3. 0不能开头
public class WrapperClassText {
    public static void main(String[] args) {
    }

    private static void myParseInt() {
        String str = "123456657";
        //校验字符串
        String regx = "[1-9]\\d{0,9}";
        if (str.matches(regx)) {
            int num = 0;
            //遍历字符串拿出每一个字符
            for (int i = 0; i < str.length(); i++) {
                char ch = str.charAt(i);
                int n = ch - '0';
                num = num * 10 + n;
            }
            System.out.println("输入的数据为:" + num);
        } else System.out.println("输入的数据非法");
    }
}

# 定义一个方法实现toBinaryString方法 将一个十进制数转换成二进制

public class WrapperClassText {
    public static void main(String[] args) {
      myToBinaryString(100);
    }
  private static void myToBinaryString(int number) {
    //核心逻辑,不断的去除以2 得到余数 直到商为0
    //还需要把余数倒着拼接起来

    //定义一个stringBuilder用来拼接字符串
    StringBuilder sb = new StringBuilder();

    while (number != 0) {
      sb.insert(0, number % 2);
      number = number / 2;
    }
    System.out.println("二进制结果为" + sb.toString());
  }
}

# 请使用代码计算你活了几天 请使用jdk7和jdk8两种方法实现

public class WrapperClassText {
    public static void main(String[] args)  {
      myLiveDaysJdk7();
      myLiveDaysJdk8();
    }
  private static void myLiveDaysJdk8() {
    //获取出生日期
    LocalDate birthday = LocalDate.of(1999, 7, 31);
    //获取当前日期
    LocalDate now = LocalDate.now();
    //获取两个时间的间隔天数
    long between = ChronoUnit.DAYS.between(birthday, now);
    System.out.println("活了" + between + "天");
  }

  private static void myLiveDaysJdk7() {
    //jdk7中只要对时间进行计算或判断都需要先获取时间的毫秒值
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    //1.获取出生年月日的毫秒值
    String birthday = "1999-07-31";
    //将字符串时间转换为Date对象
    Date parse = sdf.parse(birthday);
    //将date对象转化为时间毫秒值
    long birthdayTime = parse.getTime();
    //2.获取当前时间的毫秒值
    long nowTime = System.currentTimeMillis();
    //得到间隔时间
    long intervalTime = nowTime - birthdayTime;
    //获取天数
    long days = intervalTime / (1000 * 60 * 60 * 24);
    System.out.println("活了" + days + "天");
  }
}

# 判断任意的一个年份是闰年还是平年

  • 要求:用Jdk7和jdk8两种方式判断 提示
  • 二月有29天是闰年
  • 一年有366天是闰年
public class WrapperClassText {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    System.out.println("请输入一个年份");
    String year = sc.nextLine();
    myLeapYearJdk7(year);
    myLeapYearJdk8(year);
  }
  private static void myLeapYearJdk7(String year) {
    Calendar instance = Calendar.getInstance();
    //设置日期为当年的3月1日
    instance.set(Integer.parseInt(year), 2, 1);
    //减去一天获取二月最后一天
    instance.add(Calendar.DAY_OF_MONTH, -1);
    //二月份最后一天的日期
    int day = instance.get(Calendar.DAY_OF_MONTH);
    System.out.println("最后一天是" + day);
    if (day == 29) {
      System.out.println(year + "jdk7是闰年");
    } else {
      System.out.println(year + "jdk7不是闰年");
    }
  }

  private static void myLeapYearJdk8(String year) {
    LocalDate yearDate = LocalDate.of(Integer.parseInt(year), 1, 1);
    if (yearDate.isLeapYear()) {
      System.out.println(year + "jdk8是闰年");
    } else {
      System.out.println(year + "jdk8不是闰年");
    }
  }
}

# 操作数组的工具类Arrays

方法 描述
public static String toString(int[] a) 将数组转换为字符串表示形式。
public static int binarySearch(int[] a, int key) 二分查找法查找元素
public static void fill(int[] a, int val) 使用指定的值填充数组
public static int[] copyOf(int[] original, int newLength) 创建一个新的数组
public static int[] copyOfRange(int[] original, int from, int to) 创建一个新的数组(指定范围)
public static void sort(int[] a) 按照默认方式对数组进行排序。
public static void sort(int[] a, 排序规则) 按照指定的规则进行排序

# 集合工具类 Collections

# Collections常用API

方法 描述
public static <T> boolean addAll(List<T> c, T... elements) 向集合中批量添加元素
public static <T> void shuffle(List<T> list) 将集合中的元素随机排序
public static <T> void sort(List<T> list) 将集合中的元素按照默认规则排序
public static <T> void sort(List<T> list, Comparator<? super T> c) 将集合中的元素按照指定的规则排序
public static <T> int binarySearch(List<? extends Comparable<? super T>> a, T key) 二分查找法查找元素
public static <T> void copy (List<? super T> dest, List<? extends T> src) 拷贝集合中的元素
public static <T> void fill(List<? super T> list, T obj) 使用指定的元素填充集合
public static <T> T max/min(Collection<? extends T> coll) 根据默认的自然排序获取最大/最小值
public static <T> void swap(List<?> list, int i, int j) 交换集合中指定位置的数据

# 练习

package practice;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
import java.util.Scanner;

public class text {
    static Random random = new Random();

    private static class Student {
        private String name;
        private int age;
        private String sex;

        public Student(String name, int age, String sex) {
            this.name = name;
            this.age = age;
            this.sex = sex;
        }

        public String getName() {
            return name;
        }

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

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public String getSex() {
            return sex;
        }

        public void setSex(String sex) {
            this.sex = sex;
        }
    }

    public static void main(String[] args) {
        //练习
        //学生名字
        //班级里有n个学生,学生属性 姓名,年龄,性别
        String[] names = {"张三", "李四", "王五", "赵六", "钱七", "孙八", "周九", "吴十"};
        String[] sexs = {"男", "女"};
        ArrayList<Student> list = new ArrayList<>();

        //循环添加数据
        for (String name : names)
            list.add(new Student(name, random.nextInt(20) + 15, sexs[random.nextInt(2)]));


        //1.实现随机点名器
        //随机拿取数据
        System.out.println(list.get(random.nextInt(list.size())).getName());

        //2.概率点名
        point(list);


        //已经点过的学生不再点到
        Scanner sc = new Scanner(System.in);
        ArrayList<Student> pointList = new ArrayList<>(Collections.nCopies(list.size(), null));
        Collections.copy(pointList, list);
        int count = 0;
        int num = 1;
        System.out.println("开始点名----------");
        while (count <= 100) {
            Student student = point(pointList);
            if (student == null) throw new RuntimeException("没有学生了");
            pointList.remove(student);
            if (pointList.isEmpty()) {
                //重新开始下一轮点名
                pointList.addAll(list);
                System.out.println("第" + ++num + "轮点名");
            }
            count++;
        }
    }

    //概率点名
    private static Student point(ArrayList<Student> list) {
        //男生30% 女生70%概率
        int find = random.nextInt(11) + 1;
        //男生
        ArrayList<Student> boy = new ArrayList<>();
        //女生
        ArrayList<Student> girl = new ArrayList<>();
        for (Student student : list)
            if (student.getSex().equals("男"))
                boy.add(student);
            else girl.add(student);

        Student student;
        if (find <= 3) {
            student = pointStudent(boy);
            if (student == null) return pointStudent(girl);
        } else {
            student = pointStudent(girl);
            if (student == null) return pointStudent(boy);
        }
        return student;
    }

    //点名函数
    private static Student pointStudent(ArrayList<Student> list) {
        if (list.isEmpty()) return null;
        Collections.shuffle(list);
        System.out.println(list.getFirst().getName() + ":" + list.getFirst().getSex());
        return list.getFirst();
    }


}



上次更新: 10/23/2024, 10:13:35 AM