Java常用类


目录
  • 常用类
    • 字符串相关的类:String
      • 创建字符串对象的2种方法
      • String常见面试题
      • String类常用API-字符串内容比较
      • String类常用API-遍历、替换、截取、分割操作
      • String案例操作
    • ArrayList
      • 集合
      • ArrayList集合(泛型)
      • ArrayList集合案例
        • 1.遍历并删除元素值
        • 2.存储自定义类型的对象
        • 3.元素搜索
    • Object
    • Objects
    • StringBuilder
    • Math
    • System
    • BigDecimal
    • 日期时间
      • Date
      • SimpleDateFormat类作用
      • Calendar日历
      • JDK8新增曰期类
        • LocalDate、LocalTime、LocalDateTime
        • Instant时间戳(时刻)
        • DateTimeFormatter
        • Duration/Period
        • ChronoUnit
    • 包装类
    • 正则表达式
    • Arrays类
    • 常见算法
      • 选择排序
      • 二分查找(选择排序的改进)
    • Lambda表达式
      • Lambda
      • Lambda简化常见函数式接口
      • Lambda省略规则

常用类

字符串相关的类:String

  • String的特性

    • String类:代表字符串。Java程序中的所有字符串字面值(如 "abc")都作为此类的实例实现。
    • String是一个final类,代表不可变的字符序列
    • 字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。
    • String对象的字符内容是存储在一个字符数组value[]中的。
    /*
    string:字符串,使用一对""引起来表示。
    1.String声明为finaL的,不可被继承
    2.String实现了Serializable接口:表示字符串是支持序列化的。
            实现了Comparable接口:表示String可以比较大小
    3.String内部定义了final char[] value用于存储字符串数据
    4.String:代表不可变的字符序列。简称:不可变性。
       体现:1.当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。
           2.当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值
           3.当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值
    5.通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。
    6.字符串常量池中是不会存储相同内容的字符串的。
    */
    String s1="abc";//字面量的定义方式
    String s2="abc";
    //比较s1和s2的地址值
    System.out.println(s1==s2);//true
    s1="hello";
    System.out.println(s1);//hello
    System.out.println(s2);//abc
    System.out.println("*************************");
    String s3="abc";
    String s4 = s3.replace("a", "m");//replace替换
    System.out.println(s3);//abc
    System.out.println(s4);//mbc
    System.out.println("*************************");
    
  • String对象的创建

    public class Person {
        String name;
        int age;
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }
    
    /*
        String的实例化方式:
          方式一:通过字面量定义的方式
          方式二:通过new +构造器的方式
           面试题: String s = new String("abc");方式创建对象,在内存中创建了几个对象?
                  两个:一个是堆空间中new结构,另一个是char[]对应的常量池中的数据: "abc"
    */
    
    //通过字面量定义的方式:此时的s1和s2的数据javaSE声明在方法区中的字符串常量池中。
    String s1="javaSE";
    String s2="javaSE";
    //通过new + 构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值。
    String s3 = new String("javaSE");
    String s4 = new String("javaSE");
    System.out.println(s1==s2);//true
    System.out.println(s1==s3);//false
    System.out.println(s1==s4);//false
    System.out.println(s3==s4);//false
    System.out.println("*************************");
    Person p1 = new Person("Tom",12);
    Person p2 = new Person("Tom",12);
    System.out.println(p1.name.equals(p2.name));//true
    System.out.println(p1.name==p2.name);//true
    System.out.println("*************************");
    

创建字符串对象的2种方法

  • 方法一:直接使用“”定义。(推荐方式)

    String name="javaSE";
    
  • 方法二:通过String类的构造器创建对象。

    在这里插入图片描述

//方式一:直接使用双引号得到字符串对象
String name="我爱中国";
System.out.println(name);
//方式二:
//1、public String():创建一个空白字符串对象,不含有任何内容﹑(几乎不用)
String s1=new String();//s1=""
System.out.println(s1);
//2、public String(String):根据传入的字符串内容,来创建字符串对象(几乎不用)
String s2=new String("我是中国人");
System.out.println(s2);
//3、public string(char[] c):根据字符数组的内容,来创建字符串对象
char[] chars={'a','b','中'};
String s3=new String(chars);
System.out.println(s3);
//4、public String(byte[] b):根据字节数组的内容,来创建字符串对象
byte[] bytes={97,98,99,65};
String s4=new String(bytes);
System.out.println(s4);
  • 有什么区别吗?(面试常考)

    • 以“”方式给出的字符串对象,在字符串常量池中存储,而且相同内容只会在其中存储一份。
    • 通过构造器new对象,每new一次都会产生一个新对象,放在堆内存中。

    在这里插入图片描述

String常见面试题

  • 1.问题:下列代码的运行结果是,s1和s2各创建了几个对象?(答案:[1]

    在这里插入图片描述

  • 2.问题:下列代码的运行结果是?(答案:[2]

    在这里插入图片描述

  • 2.问题:下列代码的运行结果是?(答案:[3]

    在这里插入图片描述

String类常用API-字符串内容比较

//1、正确登录名和密码
String okName="admin";
String okPassword="123";
//2、请您输入登录名称和密码
Scanner scanner = new Scanner(System.in);
System.out.println(" 登录名称:");
String name = scanner.next();
System.out.println("登录密码:");
String password = scanner.next();
//3、判断用户输入的登录名称和密码与正确的内容是否相等。
if (okName==name && okPassword==password){
    System.out.println("登录成功");
}else {
    System.out.println("用户名或密码错误");
}

结果:

登录名称:
admin
登录密码:
123
用户名或密码错误

结论:字符串的内容比较不适合用"==”比较。

  • 字符串的内容比较:
    • 推荐使用String类提供的“equals”比较:只关心内容一样即可
//4、忽略大小写比较内容的Api:一般用于比较验证码这样的业务逻辑
String sysCode="23AdFh";
String code1="23aDfH";
System.out.println(sysCode.equals(code1));//false
System.out.println(sysCode.equalsIgnoreCase(code1));//true忽略大小写
  • 总结:
    1. 如果是字符串比较应该使用使用什么方式进行比较,为什么
      • 使用String提供的equlas方法
      • 只关心内容一样就返回true
    2. 开发中什么时候使用==比较数据
      • 基本数据类型比较时使用

String类常用API-遍历、替换、截取、分割操作

  • String常用API

在这里插入图片描述

//1、public int length():获取字符串的长度
String name="我爱中国";
System.out.println(name.length());
//2、public char charAt(int index):获取某个索引位置处的字符
char c=name.charAt(1);
System.out.println(c);//爱
System.out.println("--------遍历字符串中的每个字符--------");
for (int i = 0; i < name.length(); i++) {
    char c1 = name.charAt(i);
    System.out.println(c1);
}
//3、public char[] toCharArray()::把字符串转换成字符数组
char[] chars=name.toCharArray();
System.out.println("--------遍历字符串中的每个字符--------");
for (int i = 0; i < name.length(); i++) {
    char c2 = chars[i];
    System.out.println(c2);
}
System.out.println("----------------");
//4、public String substring(int beginIndex, int endIndex) :包前不包后的
String name2="Java是最厉害的编程语言";
String rs1 = name2.substring(0, 9);
System.out.println(rs1);//Java是最厉害的
String rs2 = name2.substring(4, 9);
System.out.println(rs2);//是最厉害的

//5、public String substring(int beginIndex):从当前索引一直截取到末尾
String rs3 = name2.substring(4);
System.out.println(rs3);//是最厉害的编程语言
//6、public String replace(CharSequence target,CharSequence replacement):替换为
String name3 = "Java是最厉害的编程语言,Java无敌";
String rs4=name3.replace("Java","***");
System.out.println(rs4);//***是最厉害的编程语言,***无敌
//7、public boolean contains(CharSequence s):是否包含
System.out.println(name3.contains("Java"));//true
System.out.println(name3.contains("java"));//false
//8、public boolean startsWith ( string prefix):是否已它为开始
System.out.println(name3.startsWith("Java"));//true
System.out.println(name3.startsWith("Java是最厉害的"));//true
System.out.println(name3.startsWith("java是最厉害的2"));//false
//9、public String[] split(String s):按照某个内容把字符串分割成字符串数组返回。
String name4="Java,C#,C++";
String[] names=name4.split(",");
for (int i = 0; i < names.length; i++) {
    System.out.println("选择了:"+names[i]);
    //选择了:Java
    //选择了:C#
    //选择了:C++
}

String案例操作

String类开发验证码功能:

需求:

  • 随机产生一个5位的验证码,每位可能是数字、大写字母、小写字母。

分析:

  • 定义一个String类型的变量存储验a-zA-Z0-9之间的全部字符。
  • 循环5次,随机一个范围内的索引,获取对应字符连接起来即可。
//1、定义可能出现的字符信息
String datas="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
//2、循环5次,每次生成一个随机的索引,提取对应的字符连接起来即可
String code="";
Random random=new Random();
for (int i = 0; i < 5; i++) {
    //随机一个索引
    int anInt = random.nextInt(datas.length());
    char c = datas.charAt(anInt);
    code+=c;
}
//3、输出字符串变量即可
System.out.println(code);

练习题1: (模拟用户登录)

//1、定义正确的登录名称和密码
String okLoginName="admin";
String okPassword="123";
//2、定义一个循环,循环3次,让用户登录
Scanner scanner = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
    System.out.println("请您输入登录名称:");
    String loginName = scanner.next();
    System.out.println("请您输入登录密码:");
    String password = scanner.next();
    //3、判断登录是否成功!
    if (okLoginName.equals(loginName)){
        //4、判断密码是否正确
        if (okPassword.equals(password)){
            System.out.println("登录成功");
            break;
        }else {
            System.out.println("登录密码错误"+",您还剩余"+(3-i)+"次机会");
        }
    }else {
        System.out.println("登录名称错误"+",您还剩余"+(3-i)+"次机会");
    }
}

练习题2: (手机号码屏蔽)

需求:

  • 以字符串的形式从键盘接受一个手机号,将中间四位号码屏蔽,最终效果为:176****1111

分析:

  • 键盘录入一个字符串,用Scanner 实现。
  • 截取字符串前三位,截取字符串后四位。
//1、键盘录入一个手机号码
Scanner scanner = new Scanner(System.in);
System.out.println("请您输入您的手机号码:");
String tel = scanner.next();
//2、截取号码的前三位,后四位  17612341111
String before = tel.substring(0, 3);//0 1 2
String after = tel.substring(7);//从索引7开始截取到手机号码的末尾
String s=before+"****"+after;
System.out.println(s);

ArrayList

集合

  • 集合是与数组类似,也是一种容器,用于装数据的。
  • 数组定义完成并启动后,类型确定、长度固定。
  • 特点:
    • 集合的大小不固定,启动后可以动态变化,类型也可以选择不固定。
    • 集合非常适合做元素个数不确定,且要进行增删操作的业务场景。
    • 集合的提供了许多丰富、好用的功能,而数组的功能很单一。

总结:

  1. 数组和集合的元素存储的个数问题?
    • 数组定义后类型确定,长度固定
    • 集合类型可以不固定,大小是可变的。
  2. 数组和集合适合的场景
    • 数组适合做数据个数和类型确定的场景
    • 集合适合做数据个数不确定,且要做增删元素的场景
  • ArrayList集合

    ArrayList是集合中的一种,它支持索引。

  • ArrayList集合的对象获取

在这里插入图片描述

  • ArrayList集合添加元素的方法

在这里插入图片描述

//1、创建ArrayList集合的对象
ArrayList list = new ArrayList();
//2、添加数据
list.add("Java");
list.add("MySQL");
list.add(23);
list.add(false);
System.out.println(list.add("Java"));//true
System.out.println(list);//[Java, MySQL, 23, false, Java]
//3、给指定索引位置插入元素
list.add(1,"C++");
System.out.println(list);//[Java, C++, MySQL, 23, false, Java]

ArrayList集合(泛型)

泛型概述

  • ArrayList:其实就是一个泛型类,可以在编译阶段约束集合对象只能操作某种数据类型。

举例:

  • ArrayList :此集合只能操作字符串类型的元素
  • ArrayList:此集合只能操作整数类型的元素

ArrayList集合常用方法:

在这里插入图片描述

注意:集合中只能存储引用类型,不支持基本数据类型。

ArrayList list = new ArrayList<>();
list.add("Java");
list.add("MySQL");
list.add("HTML");
list.add("C++");
//1、public E get(int index):获取某个索引位置处的元素值
String e=list.get(3);
System.out.println(e);//C++
//2、public int size():获取集合的大小(元素个数)
System.out.println(list.size());//4
//3、完成集合的遍历
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}
//4、public E remove(int index):删除某个索引位置处的元素值,并返回被删除的元素值
System.out.println(list);//[Java, MySQL, HTML, C++]
String e2=list.remove(2);
System.out.println(e2);//HTML
System.out.println(list);//[Java, MySQL, C++]
//5、public boolean remove(Object o):直接删除元素值,删除成功返回true,删除失败返回false
    //只会删除第一次出现的这个元素值,后面的不删除(元素有重复的情况)
System.out.println(list.remove("Java"));//true
System.out.println(list);//[MySQL, C++]
//6、public E set(int index,E element):修改某个索引位置处的元素值。
String e3=list.set(0,"C#");
System.out.println(e3);//MySQL
System.out.println(list);//[C#, C++]

ArrayList集合案例

1.遍历并删除元素值

需求:

  • 某个班级的考试在系统上进行,成绩大致为:98,77,66,89,79,50,100
  • 现在需要先把成绩低于80分以下的数据去掉。

分析:

  • 定义ArrayList集合存储多名学员的成绩。
  • 遍历集合每个元素,如果元素值低于80分,去掉它。
//目标:学习遍历并删除元素的正确方案。
        //1、创建一个ArrayList集合存储一个班级学生的成绩
        ArrayList scores = new ArrayList<>();
        scores.add(98);
        scores.add(77);
        scores.add(66);
        scores.add(89);
        scores.add(79);
        scores.add(50);
        scores.add(100);
        System.out.println(scores);
        //2、把低于80分的成绩从集合中去掉。
        //scores = [98,77,66,89,79,50,100]
        //          0  1  2  3  4  5   6
        /*
            有毛病的代码!
         */
//        for (int i = 0; i < scores.size(); i++) {
//            int score=scores.get(i);
//            if (score<80){
//                //这个分数必须删除
//                scores.remove(i);
//            }
//        }
//        System.out.println(scores);//[98, 66, 89, 50, 100]
        System.out.println("---------方法一------------");
        for (int i = 0; i < scores.size(); i++) {
            int score=scores.get(i);
            if (score<80){
                //这个分数必须删除
                scores.remove(i);
                i--;//删除成功后,必须退一步,这样可以保证下次回到这个位置,如此则不会跳过数据
            }
        }
        System.out.println(scores);//[98, 89, 100]
        System.out.println("-----------方法二-----------------");
        for (int i = scores.size()-1; i >= 0; i--) {
            int score=scores.get(i);
            if (score<80){
                //这个分数必须删除
                scores.remove(i);
            }
        }
        System.out.println(scores);//[98, 89, 100]

总结:

1、从集合中遍历元素,并筛选出元素删除它,应该怎么解决?

  • 从集合后面遍历然后删除,可以避免漏掉元素。

2.存储自定义类型的对象

需求:

  • 定义一个电影类,定义一个集合存储电影对象。
  • 创建3个电影对象,封装相关数据,把3个对象存入到集合中去。
  • 遍历集合中的3个对象,输出相关信息。
//目标:理解ArrayList集合存储自定义类型的对象。
//1、定义电影类。
//2、创建三个电影对象
//3、创建一个电影类型的ArrayList集合,存储三部电影对象
ArrayList movies = new ArrayList<>();
movies.add(new Movie("《肖生克的救赎》",9.7,"罗宾斯"));
movies.add(new Movie("《霸王别姬》",9.6,"张国荣、张丰毅"));
movies.add(new Movie("《阿甘正传》",9.5,"汤姆.汉克斯"));
System.out.println(movies);
//4、遍历电影类型的集合中的每个电影对象。访问它的信息即可。
for (int i = 0; i < movies.size(); i++) {
    //i = 0 1 2
    Movie m = movies.get(i);
    System.out.println("电影名称:"+m.getName());
    System.out.println("电影得分:"+m.getScore());
    System.out.println("电影主演:"+m.getActor());
    System.out.println("--------------------");
}

3.元素搜索

需求:

  • 后台程序需要存储如上学生信息并展示,然后要提供按照学号搜索学生信息的功能。

分析:

  • 定义Student类,定义ArrayList集合存储如上学生对象信息,并遍历展示出来。
  • 提供一个方法,可以接收ArrayList集合,和要搜索的学号,返回搜索到的学生对象信息,并展示。
  • 使用死循环,让用户可以不停的搜索。
//1、定义学生类。
    //2、创建学生对象封装学生对象
    //把学生对象添加到集合中去。
    ArrayList students = new ArrayList<>();
    students.add(new Student("20180302","叶孤城",23,"护理一班"));
    students.add(new Student("20180303","东方不败",23,"推拿二班"));
    students.add(new Student("20180304","西门吹雪",26,"中药学四班"));
    students.add(new Student("20180305","梅超风",26,"神经科2班"));
    //3、遍历这些学生信息展示。
    System.out.println("学号\t名称\t年龄\t班级");
    for (int i = 0; i < students.size(); i++) {
        Student s = students.get(i);
        System.out.println(s.getStudentNumber()+"\t"+s.getName()+"\t"+s.getAge()+"\t"+s.getClassName());
    }
    //4、定义方法完成按照学号的搜索功能。
    Scanner scanner = new Scanner(System.in);
    while (true){
        System.out.println("请您输入学号查询学生对象:");
        String studyNumber = scanner.next();
        //5、调用方法查询
        Student s = getStudentById(students, studyNumber);
        //6、判断s中是否存在学生对象地址
        if (s==null){
            System.out.println("对不起,查无此人");
        }else {
            System.out.println("您查询的学生信息如下:");
            System.out.println(s.getStudentNumber()+"\t"+s.getName()+"\t"+s.getAge()+"\t"+s.getClassName());
        }
    }
}
public static Student getStudentById(ArrayList students,String studentNumber){
    //1、遍历全部学生对象
    for (int i = 0; i < students.size(); i++) {
        Student s = students.get(i);
        //2、询问当前遍历的这个学生对象的学号,是否是我们要找的学号
        if (s.getStudentNumber().equals(studentNumber)){
            //这个s代表的学生对象,就是我们要找的:返回它
            return s;
        }
    }
    //查无此人
    return null;

Object

  • Object类的作用
    • 一个类要么默认继承了Object类,要么间接继承了Object类,Object类是Java中的祖宗类。
    • object类的方法是一切子类都可以直接使用的,所以我们要学习Object类的方法。
  • Object类的常用方法

在这里插入图片描述

  • toString存在的意义
    • 默认是打印当前对象的地址。
    • 让子类重写,以便返回子类对象的内容。
    • 父类toString()方法存在的意义就是为了被子类重写,以便返回对象的内容信息,而不是地址信息!!
  • equals存在的意义
    • 默认是与另一个对象比较地址是否一样
    • 让子类重写,以便比较2个子类对象的内容是否相同。
    • 父类equals方法存在的意义就是为了被子类重写,以便子类自己来定制比较规则。

Objects

  • Objects的常用方法

在这里插入图片描述

String name="Java";
String name1="Java";
System.out.println(Objects.equals(name,name1));//true
String name=null;
System.out.println(Objects.isNull(name));//true
  • 总结(对象进行内容比较的时候建议使用什么?为什么?)
    • 建议使用Objects提供的equals方法。
    • 比较的结果是一样的,但是更安全。

StringBuilder

  • StringBuilder概述
    • StringBuilder是一个可变的字符串类,我们可以把它看成是一个对象容器。
    • 作用:提高字符串的操作效率,如拼接、修改等。
  • StringBuilder构造器

在这里插入图片描述

  • StringBuilder常用方法

在这里插入图片描述

StringBuilder sb = new StringBuilder();
sb.append("a");
sb.append(1);
sb.append(false);
System.out.println(sb);//a1false
StringBuilder sb1 = new StringBuilder();
//支持链式编程
sb1.append("我").append(20).append(1314);
System.out.println(sb1);//我201314
//反转
sb1.reverse().append("反转");
System.out.println(sb1);//413102我反转
System.out.println(sb1.length());//9

// 注意: StringBuilder只是拼接字符串的手段:效率好。
// 最终的目的还是要恢复成String类型。
StringBuilder sb2 = new StringBuilder();
sb2.append("123");
// 恢复成String
String rs=sb2.toString();
System.out.println(rs);//123恢复成String类型
  • 总结(为什么拼接、反转字符串建议使用StringBuilder?)
    • String :内容是不可变的、拼接字符串性能差。
    • StringBuilder:内容是可变的、拼接字符串性能好、代码优雅。
    • 定义字符串使用String
    • 拼接、修改等操作字符串使用StringBuilder

Math

  • 包含执行基本数字运算的方法,Math类没有提供公开的构造器。
  • Math类的常用方法

在这里插入图片描述

//1.取绝对值:返回正数
System.out.println(Math.abs(10));//10
System.out.println(Math.abs(-10.3));//10.3
//2.向上取整:5
System.out.println(Math.ceil(4.0000001));//5.0
System.out.println(Math.ceil(4.0));//4.0
//3.向下取整:4
System.out.println(Math.floor(4.99999));//4.0
System.out.println(Math.floor(4.0));//4.0
//4.求指数次方
System.out.println(Math.pow(2,3));//8.0
//5.四舍五入 10
System.out.println(Math.round(4.49999));//4
System.out.println(Math.round(4.50001));//5
//随机数0-1之间的随机数(包前不包后)
System.out.println(Math.random());//0.0-1.0之间
//拓展: 3 - 9之间的随机数(0 - 6)+ 3
//[0 - 6] +3
int data=(int) (Math.random()*7)+3;
System.out.println(data);//9

System

  • System类概述
    • System的功能是通用的,都是直接用类名调用即可,所以System不能被实例化。
  • System类的常用方法

在这里插入图片描述

//计算机认为时间有起源:返回1970-1-1 00:00:00走到此刻的总的毫秒值:时间毫秒值。
long time=System.currentTimeMillis();
System.out.println(time);

long starTime=System.currentTimeMillis();
//进行时间的计算:性能分析
for (int i = 0; i < 100000; i++) {
    System.out.println("输出:"+i);
}
long endTime=System.currentTimeMillis();
System.out.println((endTime-starTime)/1000.0+"s");
//做数组拷贝(了解)
/*
    arraycopy(Object src,
              int  srcPos,
              Object dest,
              int destPos,
              int length);
    参数一:被拷贝的数组
    参数二:从哪个索引位置开始拷贝
    参数三:复制的目标数组
    参数四:粘贴位置
    参数五:拷贝元素的个数
 */
int[] arr1={10,20,30,40,50,60,70};
int[] arr2=new int[6];//[0, 0, 0, 0, 0, 0]==>[0, 0, 40, 50, 60, 0]
System.arraycopy(arr1,3,arr2,2,3);
System.out.println(Arrays.toString(arr2));//[0, 0, 40, 50, 60, 0]

BigDecimal

  • BigDecimal作用
    • 用于解决浮点型运算精度失真的问题
  • 使用步骤
    • 创建对象BigDecimal封装浮点型数据(最好的方式是调用方法)
  • BigDecima常用API

在这里插入图片描述

//浮点型运算的时候直接+ * / 可能会出现数据失真(精度问题)。
System.out.println(0.09+0.01);
System.out.println(1.0-0.32);
System.out.println(1.015*100);
System.out.println(1.301/100);

System.out.println("------------------");
double a=0.1;
double b=0.2;
double c=a+b;
System.out.println(c);
System.out.println("------------------");
//包装浮点型数据成为大数据对象  BigDecimal
BigDecimal a1=BigDecimal.valueOf(a);
BigDecimal b1=BigDecimal.valueOf(b);
//加
BigDecimal c1=a1.add(b1);
//减
BigDecimal c2=a1.subtract(b1);
//乘
BigDecimal c3=a1.multiply(b1);
//除
BigDecimal c4=a1.divide(b1);

System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println("------------------");
//目的:double
double rs1=c1.doubleValue();
double rs2=c2.doubleValue();
double rs3=c3.doubleValue();
double rs4=c4.doubleValue();

System.out.println(rs1);
System.out.println(rs2);
System.out.println(rs3);
System.out.println(rs4);
System.out.println("------------------");
//注意事项:BigDecimal是一定要精度运算的
BigDecimal a11=BigDecimal.valueOf(10.0);
BigDecimal b11=BigDecimal.valueOf(3.0);
//BigDecimal c11=a11.divide(b11);//3.33333333 会报错
/*
参数一:除数  参数二:保留小数位数  参数三:舍入模式
 */
BigDecimal c11=a11.divide(b11,2, RoundingMode.HALF_UP);//保留两位小数
System.out.println(c11);

日期时间

Date

  • Date类概述
    • Date类的对象在Java中代表的是当前所在系统的此刻日期时间。

在这里插入图片描述

在这里插入图片描述

  • Date类记录时间的2种形式

    • 形式1:日期对象
    //1、创建一个Date类的对象:代表系统此刻日期时间对象
    Date date = new Date();
    System.out.println(date);
    
    • 形式2:时间毫秒值
      • 指的是从1970年1月1日00:00:00走到此刻的总的毫秒数,应该是很大的
    //2、获取当前时间毫秒值
    long time= date.getTime();
    System.out.println(time);
    
  • 时间毫秒值->日期对象

在这里插入图片描述

在这里插入图片描述

  • 案例
/*
    请计算出当前时间往后走1小时121秒之后的时间是多少。
 */
//1、得到当前时间毫秒值
Date date1 = new Date();
System.out.println(date1);
//2、当前时间往后走1小时 121s
long time2=System.currentTimeMillis();
time2+=(60*60+121)*1000;
//3、把时间毫秒值转换成对应的日期对象
//第一种
Date date2 = new Date(time2);
System.out.println(date2);
//第二种
Date date3 = new Date();
date3.setTime(time2);
System.out.println(date3);

SimpleDateFormat类作用

  • 可以对Date对象或时间毫秒值格式化成我们喜欢的时间形式。
  • 也可以把字符串的时间形式解析成日期对象。

在这里插入图片描述

  • SimpleDateFormat的构造器

在这里插入图片描述

  • SimpleDateFormat的格式化方法

在这里插入图片描述

  • 格式化的时间形式的常用的模式对应关系如下:

在这里插入图片描述

//1、日期对象
Date date = new Date();
System.out.println(date);//Wed Mar 23 15:44:06 CST 2022
//2、格式化这个日期对象〔指定最终格式化的形式):EEE(星期几) a(上午或下午)yyyy年MM月dd日 HH:mm:ss EEE a
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss EEE a");
//3、开始格式化日期对象成为喜欢的字符串形式
String rs=sdf.format(date);
System.out.println(rs);//2022-03-23 15:44:06 星期三 下午
System.out.println("------------------");
//4、格式化时间毫秒值
//需求:请问121秒后的时间是多少
long time=System.currentTimeMillis()+121*1000;
String rs1=sdf.format(time);
System.out.println(rs1);//2022-03-23 15:46:07 星期三 下午
  • SimpleDateFormat解析字符串时间成为日期对象

在这里插入图片描述

System.out.println("---------解析字符串时间---------");
//目标:学会使用SimpleDateFormat解析字符串时间成为日期对象。
//请计算出2022年03月23日 11:11:11,往后走2天14小时49分06秒后的时间是多少。
//1、把字符串时间拿到程序中来
String dateStr="2022年03月23日 11:11:11";
//2、把字符串时间解析成日期对象:形式必须与被解析时间的形式完全一样,否则运行时解析报错!
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date d = sdf1.parse(dateStr);
//3、往后走2天14小时49分06秒
long time1=d.getTime()+(2L*24*60*60+14*60*60+49*60+6)*1000;
//4、格式化这个时间毫秒值就是结果
System.out.println(sdf1.format(time1));//2022年03月26日 02:00:17

案例:

  • 秒杀开始时间:2020年11月11日 00:00:00
  • 秒杀结束时间:2020年11月11日 00:10:00

  • 需求:
    • 小贾下单并付款的时间为:2020年11月11日 00:03:47
    • 小皮下单并付款的时间为:2020年11月11日 00:10:17
    • 用代码说明这两位同学有没有参加上秒杀活动?
  • 分析:
    • 判断下单时间是否在开始到结束的范围内。
    • 把字符串形式的时间变成毫秒值。

//1、开始 和 结束时间
String startTime="2020年11月11日 00:00:00";
String endTime="2020年11月11日 00:10:00";
//2、小贾  小皮
String xiaoJia="2020年11月11日 0:03:47";
String xiaoPi="2020年11月11日 0:10:17";
//3、解析他们的时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date startDate=sdf.parse(startTime);
Date endDate=sdf.parse(endTime);
Date jiaDate=sdf.parse(xiaoJia);
Date piDate=sdf.parse(xiaoPi);
//after(在...之后)  before(在...之前)
if (jiaDate.after(startDate) && jiaDate.before(endDate)){
    System.out.println("小贾秒杀成功,可以发货了");
}else {
    System.out.println("小贾秒杀失败");
}

if (piDate.after(startDate) && piDate.before(endDate)){
    System.out.println("小皮秒杀成功,可以发货了");
}else {
    System.out.println("小皮秒杀失败");
}

Calendar日历

  • Calendar代表了系统此刻日期对应的日历对象。
  • Calendar是一个抽象类,不能直接创建对象。
  • Calendar日历类创建日历对象的方法:

在这里插入图片描述

  • Calendar常用方法

在这里插入图片描述

  • 注意:calendar是可变日期对象,一旦修改后其对象本身表示的时间将产生变化。
//1、拿到系统此刻日历对象
Calendar cal = Calendar.getInstance();
System.out.println(cal);
//2、获取日历的信息
int year=cal.get(Calendar.YEAR);
System.out.println(year+"年");
int month=cal.get(Calendar.MONTH)+1;
System.out.println(month+"月");
int days=cal.get(Calendar.DAY_OF_YEAR);
System.out.println(days+"天");
//3、public void set(int field,int value):修改日历的某个字段信息。
//cal.set(Calendar.HOUR,12);
//System.out.println(cal);//HOUR=12

//4、public void add(int field,int amount):为某个字段增加/减少指定的值
//请问64天后是什么时间
cal.add(Calendar.DAY_OF_YEAR,64);
System.out.println(cal);
//5、public final Date getTime():拿到此刻日期对象。
Date date = cal.getTime();
System.out.println(date);
//6、public long getTimeInMillis():拿到此刻时间毫秒值
long time=cal.getTimeInMillis();
System.out.println(time);

JDK8新增曰期类

  • 从Java8开始,java.time包提供了新的日期和时间API,主要涉及的类型有:

在这里插入图片描述

  • 新增的API严格区分了时刻、本地日期、本地时间,并且,对日期和时间进行运算更加方便。
  • 其次,新API的类型几乎全部是不变类型(和String的使用类似),可以放心使用不必担心被修改。

LocalDate、LocalTime、LocalDateTime

  • LocalDate、LocalTime、LocalDateTime
    • 他们分别表示日期,时间,日期时间对象,他们的类的实例是不可变的对象。
    • 他们三者构建对象和API都是通用的
  • 构建对象的方式如下:

在这里插入图片描述

  • LocalDate
//1、获取本地日期对象。
LocalDate nowDate =LocalDate.now();
System.out.println("今天的日期:"+nowDate);//今天的日期:2022-03-24

int year= nowDate.getYear();
System.out.println(year+"年");//2022年

int month= nowDate.getMonthValue();
System.out.println(month+"月");//3月

int day= nowDate.getDayOfMonth();
System.out.println(day+"日");//24日

//当年的第几天
int dayOfYear= nowDate.getDayOfYear();
System.out.println("当年的第"+dayOfYear+"天");//当年的第83天

//星期
System.out.println("星期"+nowDate.getDayOfWeek());//星期THURSDAY
System.out.println("星期"+nowDate.getDayOfWeek().getValue());//星期4
//月份
System.out.println(nowDate.getMonth()+"月份");//MARCH月份
System.out.println(nowDate.getMonth().getValue()+"月份");//3月份

System.out.println("--------------------");
LocalDate bt =LocalDate.of(1991,11,11);
System.out.println(bt);//直接传入对应的年月日  //1991-11-11
System.out.println(LocalDate.of(1991, Month.NOVEMBER,11));//1991-11-11
  • LocalTime
//1、获取本地日期对象。
LocalTime nowTime = LocalTime.now();
System.out.println("今天的日期:"+nowTime);//今天的日期:16:58:35.979

int hour= nowTime.getHour();
System.out.println(hour+"时");//16时

int minute= nowTime.getMinute();
System.out.println(minute+"分");//58分

int second= nowTime.getSecond();
System.out.println(second+"秒");//35秒

int nano= nowTime.getNano();
System.out.println(nano+"纳秒");//979000000纳秒

System.out.println("----------------------");
System.out.println(LocalTime.of(8,20));//时分
System.out.println(LocalTime.of(8,20,30));//时分秒
System.out.println(LocalTime.of(8,20,30,150));//时分秒纳
LocalTime mTime = LocalTime.of(8,20,30,150);

System.out.println("--------------------");
System.out.println(LocalDateTime.of(1991,11,11,8,20));//年月日时分
System.out.println(LocalDateTime.of(1991, Month.NOVEMBER,11,8,20));//年月日时分
System.out.println(LocalDateTime.of(1991,11,11,8,20,30));//年月日时分秒
System.out.println(LocalDateTime.of(1991, Month.NOVEMBER,11,8,20,30));//年月日时分秒
System.out.println(LocalDateTime.of(1991,11,11,8,20,30,40));//年月日时分秒纳
System.out.println(LocalDateTime.of(1991, Month.NOVEMBER,11,8,20,30,40));//年月日时分秒纳
  • LocalDateTime
//日期  时间
LocalDateTime nowDateTime = LocalDateTime.now();
System.out.println("今天是:"+nowDateTime);//今天是:2022-03-24T17:17:26.167
System.out.println(nowDateTime.getYear()+"年");//2022年
System.out.println(nowDateTime.getMonthValue()+"月");//3月
System.out.println(nowDateTime.getDayOfMonth()+"日");//24日
System.out.println(nowDateTime.getHour()+"时");//17时
System.out.println(nowDateTime.getMinute()+"分");//17分
System.out.println(nowDateTime.getSecond()+"秒");//26秒
System.out.println(nowDateTime.getNano()+"纳");//167000000纳
//日:当年的第几天
System.out.println("当年的第"+nowDateTime.getDayOfYear()+"天");//当年的第83天
//星期
System.out.println("星期"+nowDateTime.getDayOfWeek());//星期THURSDAY
System.out.println("星期"+nowDateTime.getDayOfWeek().getValue());//星期4
//月份
System.out.println(nowDateTime.getMonth()+"月份");//MARCH月份
System.out.println(nowDateTime.getMonth().getValue()+"月份");//3月份
  • 转换

在这里插入图片描述

//转换LocalDate
LocalDate ld =nowDateTime.toLocalDate();
System.out.println(ld);//2022-03-24
//转换LocalTime
LocalTime lt =nowDateTime.toLocalTime();
System.out.println(lt.getHour());//17时
System.out.println(lt.getMinute());//17分
System.out.println(lt.getSecond());//26秒
  • 修改相关的API
    • LocalDateTime综合了LocalDate和LocalTime里面的方法,所以下面只用LocalDate和LocalTime来举例。
    • 这些方法返回的是一个新的实例引用,因为LocalDateTime 、 LocalDate 、 LocalTime都是不可变的。

在这里插入图片描述

LocalTime nowTime = LocalTime.now();
System.out.println(nowTime);//当前时间 17:29:49.255
System.out.println(nowTime.minusHours(1));//一小时前 16:29:49.255
System.out.println(nowTime.minusMinutes(1));//一分钟前 17:28:49.255
System.out.println(nowTime.minusSeconds(1));//一秒前 17:29:48.255
System.out.println(nowTime.minusNanos(1));//一纳秒前 17:29:49.254999999
System.out.println("----------------------");

System.out.println(nowTime.plusHours(1));//一小时后 18:29:49.255
System.out.println(nowTime.plusMinutes(1));//一分钟后 17:30:49.255
System.out.println(nowTime.plusSeconds(1));//一秒后 17:29:50.255
System.out.println(nowTime.plusNanos(1));//一纳秒后 17:29:49.255000001
System.out.println("----------------------");
LocalDate myDate = LocalDate.of(2018, 9, 5);
LocalDate nowDate = LocalDate.now();

System.out.println("今天是2018-09-06吗?"+nowDate.equals(myDate));//今天是2018-09-06吗?false
System.out.println(myDate+"是否在"+nowDate+"之前?"+myDate.isBefore(nowDate));//2018-09-05是否在2022-03-24之前?true
System.out.println(myDate+"是否在"+nowDate+"之后?"+myDate.isAfter(nowDate));//2018-09-05是否在2022-03-24之后?false

System.out.println("-------------------------");
//判断今天是否是你的生日
LocalDate birDate = LocalDate.of(1999, 8, 21);//生日的时间
LocalDate nowDate1 = LocalDate.now();//当前的时间
MonthDay birMd = MonthDay.of(birDate.getMonthValue(), birDate.getDayOfMonth());//获取生日的:月和日
MonthDay nowMd = MonthDay.from(nowDate1);//获取现在的:月和日
System.out.println("今天是你的生日吗?"+birMd.equals(nowMd));//今天是你的生日吗?false

Instant时间戳(时刻)

  • JDK8获取时间戳特别简单,且功能更丰富。Instant类由一个静态的工厂方法now()可以返回当前时间戳。
  • 时间戳是包含日期和时间的,与java.util.Date很类似,事实上Instant就是类似JDK8以前的Date。
  • Instant和Date这两个类可以进行转换。
//1、得到一个Instant时间戳对象
Instant instant = Instant.now();
System.out.println(instant);//2022-03-24T09:50:48.535Z
//2、系统此刻的时间戳怎么办?
Instant instant1 = Instant.now();
System.out.println(instant1.atZone(ZoneId.systemDefault()));//2022-03-24T17:50:48.594+08:00[Asia/Shanghai]
//3、如何去返回Date对象
Date date = Date.from(instant);
System.out.println(date);//Thu Mar 24 17:50:48 CST 2022

Instant i2 = date.toInstant();
System.out.println(i2);//2022-03-24T09:50:48.535Z

DateTimeFormatter

  • 在JDK8中,引入了一个全新的日期与时间格式器DateTimeFormatter。
  • 正反都能调用format方法。
//本地此刻 日期时间 对象
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);//2022-03-24T18:01:49.198
//解析/格式化器
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss EEE a");
//正向格式化
String ldtStr = dtf.format(ldt);
System.out.println(ldtStr);//2022-03-24 18:01:49 星期四 下午
//逆向格式化
String ldtStr1 = ldt.format(dtf);
System.out.println(ldtStr1);//2022-03-24 18:01:49 星期四 下午
//解析字符串时间
DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String dateStr="2022-03-24 11:11:11";
//解析当前字符串时间成为本地日期时间对象
LocalDateTime ldt1 = LocalDateTime.parse(dateStr, dtf1);
System.out.println(ldt1);//2022-03-24T11:11:11
System.out.println(ldt1.getDayOfYear());//一年中第83天

Duration/Period

Period:

  • 在Java8中,我们可以使用以下类来计算日期间隔差异: java.time.Period
  • 主要是Period类方法getYears(),getMonths()和getDays()来计算,只能精确到年月日。
  • 用于LocalDate 之间的比较。
//当前本地 年月日
LocalDate today = LocalDate.now();
System.out.println(today);//2022-03-24
//生日的 年月日
LocalDate birthDate = LocalDate.of(1999, 8, 21);
System.out.println(birthDate);//1999-08-21

Period period = Period.between(birthDate, today);//第二个参数减第一个参数

System.out.println(period.getYears());//22
System.out.println(period.getMonths());//7
System.out.println(period.getDays());//3

Duration:

  • 在Java8中,我们可以使用以下类来计算时间间隔差异: java.time.Duratio
  • 提供了使用基于时间的值测量时间量的方法。
  • 用于LocalDateTime之间的比较。也可用于Instant 之间的比较。
//本地日期时同对家。
LocalDateTime today = LocalDateTime.now();
System.out.println(today);//2022-03-24T19:52:04.158
//出生的日期时间对象
LocalDateTime birthDate = LocalDateTime.of(1999, 8, 21, 20, 00, 00);
System.out.println(birthDate);//1999-08-21T20:00

Duration duration = Duration.between(birthDate, today);//第二个参数减第一个参数
System.out.println(duration.toDays());//两个时间差的天数 8250
System.out.println(duration.toHours());//两个时间差的小时数 198023
System.out.println(duration.toMinutes());//两个时间差的分钟数 11881432
System.out.println(duration.toMillis());//两个时间差的毫秒数 712885924158
System.out.println(duration.toNanos());//两个时间差的纳秒数 712885924158000000

ChronoUnit

java.time.temporal.ChronoUnit

  • ChronoUnit类可用于在单个时间单位内测量一段时间,这个工具类是最全的了,可以用于比较所有的时间单位
//本地日期时间对象:此刻的
LocalDateTime today = LocalDateTime.now();
System.out.println(today);//2022-03-24T20:03:15.405
//生日时间
LocalDateTime birthDate = LocalDateTime.of(1999, 8, 21, 20, 00, 00);
System.out.println(birthDate);//1999-08-21T20:00

System.out.println("相差的年数:"+ ChronoUnit.YEARS.between(birthDate,today));//相差的年数:22
System.out.println("相差的月数:"+ ChronoUnit.MONTHS.between(birthDate,today));//相差的月数:271
System.out.println("相差的周数:"+ ChronoUnit.WEEKS.between(birthDate,today));//相差的周数:1178
System.out.println("相差的天数:"+ ChronoUnit.DAYS.between(birthDate,today));//相差的天数:8251
System.out.println("相差的时数:"+ ChronoUnit.HOURS.between(birthDate,today));//相差的时数:198024
System.out.println("相差的分数:"+ ChronoUnit.MINUTES.between(birthDate,today));//相差的分数:11881443
System.out.println("相差的秒数:"+ ChronoUnit.SECONDS.between(birthDate,today));//相差的秒数:712886595
System.out.println("相差的毫秒数:"+ ChronoUnit.MILLIS.between(birthDate,today));//相差的毫秒数:712886595405
System.out.println("相差的微秒数:"+ ChronoUnit.MICROS.between(birthDate,today));//相差的微秒数:712886595405000
System.out.println("相差的纳秒数:"+ ChronoUnit.NANOS.between(birthDate,today));//相差的纳秒数:712886595405000000
System.out.println("相差的半天数:"+ ChronoUnit.HALF_DAYS.between(birthDate,today));//相差的半天数:16502
System.out.println("相差的十年数:"+ ChronoUnit.DECADES.between(birthDate,today));//相差的十年数:2
System.out.println("相差的世纪(百年)数:"+ ChronoUnit.CENTURIES.between(birthDate,today));//相差的世纪(百年)数:0
System.out.println("相差的千年数:"+ ChronoUnit.MILLENNIA.between(birthDate,today));//相差的千年数:0
System.out.println("相差的纪元数:"+ ChronoUnit.ERAS.between(birthDate,today));//相差的纪元数:0

包装类

  • 其实就是8种基本数据类型对应的引用类型。

在这里插入图片描述

  • Java为了实现一切皆对象,为8种基本类型提供了对应的引用类型。

  • 后面的集合和泛型其实也只能支持包装类型,不支持基本数据类型。

  • 自动装箱:基本类型的数据和变量可以直接赋值给包装类型的变量。

int a=10;
Integer a1=a;//自动装箱
System.out.println(a);
System.out.println(a1);
  • 自动拆箱:包装类型的变量可以直接赋值给基本数据类型的变量。
Integer it=100;
int it1=it;//自动拆箱
System.out.println(it1);

double db=99.5;
Double db2=db;//自动装箱
double db3=db2;//自动拆箱
System.out.println(db3);
  • 包装类的特有功能:

    • 包装类的变量的默认值可以是null,容错率更高。
    //int age=null;//报错了
    Integer age1=null;
    Integer age2=0;
    
    • 可以把基本类型的数据转换成字符串类型(用处不大)
    1. 调用toString()方法得到字符串结果。
    2. 调用Integer.toString(基本类型的数据)。
    Integer i3=23;
    String rs=i3.toString();
    System.out.println(rs+1);
    
    String rs1=Integer.toString(i3);
    System.out.println(rs1+1);
    
    //可以直接+字符串得到字符串类型
    String rs2=i3+"";
    System.out.println(rs2+1);
    
    • 可以把字符串类型的数值转换成真实的数据类型(真的很有用)
    1. lnteger.parselnt("字符串类型的整数")
    2. Double.parseDouble("字符串类型的小数")。
    String number="23";
    //转换成整数
    //int ages=Integer.parseInt(number);
    int ages1=Integer.valueOf(number);
    System.out.println(ages1+1);
    
    String number1="99.9";
    //转换成小数
    //double score=Double.parseDouble(number1);
    double score1=Double.valueOf(number1);
    System.out.println(score1+0.1);
    

总结:

1、包装类是什么,目的是什么?

  • 基本数据类型对应的引用类型。
  • 实现了一切皆对象。
  • 后期集合和泛型不支持基本类型,只能使用包装类。

2、包装类有哪些特殊功能?

  • 可以把基本类型的数据转换成字符串类型(用处不大)
  • 可以把字符串类型的数值转换成真实的数据类型(真的很有用)

正则表达式

  • 正则表达式可以用一些规定的字符来制定规则,并用来校验数据格式的合法性。
//需求:校验qq号码,必须全部数字6 - 20位
Scanner scanner = new Scanner(System.in);
System.out.println("请输入6 - 20位QQ号:");
String QQ = scanner.next();
if (QQ!=null && QQ.matches("\\d{6,20}")){
    System.out.println("输入成功");
}else {
    System.out.println("输入错误");
}
scanner.close();

正则表达式的匹配规则(Pattern):

  • 字符类(默认匹配一个字符)

在这里插入图片描述

  • 预定义的字符类(默认匹配一个字符)

在这里插入图片描述

  • 贪婪的量词(配合匹配多个字符)

在这里插入图片描述

  • 字符串对象提供了匹配正则表达式规则的API
public boolean matches(String regex):判断是否匹配正则表达式,匹配返回true,不匹配返回false。
System.out.println("a".matches("[abc]"));//true
System.out.println("z".matches("[abc]"));//false
System.out.println("ab".matches("[abc]"));//false
System.out.println("ab".matches("[abc]+"));//true
  • 全面、深入学习正则表达式的规则
//public boolean matches(String regex):判断是否匹配正则表达式,匹配返回true,不匹配返回false。
//只能是 a b c
System.out.println("a".matches("[abc]"));//true
System.out.println("z".matches("[abc]"));//false
//不能出现 a b c
System.out.println("a".matches("[^abc]"));//false
System.out.println("z".matches("[^abc]"));//true

System.out.println("a".matches("\\d"));//false
System.out.println("3".matches("\\d"));//true
System.out.println("333".matches("\\d"));//false
System.out.println("z".matches("\\w"));//true
System.out.println("2".matches("\\w"));//true
System.out.println("21".matches("\\w"));//false
System.out.println("你".matches("\\w"));//false
//以上正则匹配只能校验单个字符。
System.out.println("---------------------------");

//效验密码
//必须是数字 字母 下划线 至少6位
System.out.println("ssdsc3c".matches("[\\w{6,}]"));//false
System.out.println("ssdsc".matches("[\\w{6,}]"));//false
System.out.println("ssdsda232s牛c".matches("[\\w{6,}]"));//false
System.out.println("------------------------------");

//验证。必须是数字和字符 必须是4位
System.out.println("dsd2".matches("[a-zA-Z0-9]{4}"));//true
System.out.println("A3dy".matches("[a-zA-Z0-9]{4}"));//true
System.out.println("A3dy2".matches("[a-zA-Z0-9]{4}"));//false
System.out.println("A3_y".matches("[a-zA-Z0-9]{4}"));//false
System.out.println("dsd2".matches("[\\w&&[^_]]{4}"));//true
  • 正则表达式的常见案例

需求:

  • 请编写程序模拟用户输入手机号码、验证格式正确,并给出提示,直到格式输入正确为止。
  • 请编写程序模拟用户输入邮箱号码、验证格式正确,并给出提示,直到格式输入正确为止。
  • 请编写程序模拟用户输入电话号码、验证格式正确,并给出提示,直到格式输入正确为止。

分析:

  • 定义方法,接收用户输入的数据,使用正则表达式完成检验,并给出提示。
public static void main(String[] args) {
    //目标:校验 手机号码 邮箱 电话号码
    checkPhone();
    checkEmail();
    checkTel();
}
//手机号码
public static void checkPhone(){
    Scanner scanner = new Scanner(System.in);
    while (true) {
        System.out.println("请输入您的手机号码:");
        String phone = scanner.next();
        //判断手机号码的格式是否正确
        if (phone.matches("1[3-9]\\d{9}")){
            System.out.println("手机号码格式正确,注册完成");
            break;
        }else {
            System.out.println("格式有误");
        }
    }
}
//邮箱
public static void checkEmail(){
    Scanner scanner = new Scanner(System.in);
    while (true) {
        System.out.println("请输入您的邮箱:");
        String email = scanner.next();
        //判断邮箱的格式是否正确
        //1111111@qq.com  1111111@163.com  1111111@pci.com.cn
        if (email.matches("\\w{1,30}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,20}){1,2}")){
            System.out.println("邮箱格式正确,注册完成");
            break;
        }else {
            System.out.println("格式有误");
        }
    }
}
//电话号码
public static void checkTel(){
    Scanner scanner = new Scanner(System.in);
    while (true) {
        System.out.println("请输入您的电话号码:");
        String tel = scanner.next();
        //判断电话号码的格式是否正确
        //023-12345678   02312345678
        if (tel.matches("0\\d{2,6}-?\\d{5,20}")){
            System.out.println("电话号码格式正确,注册完成");
            break;
        }else {
            System.out.println("格式有误");
        }
    }
}
  • 正则表达式在方法中的应用

在这里插入图片描述

String names="蓉儿dasdad34小龙女fhftghf455过儿";
String[] arrs=names.split("\\w+");
for (int i = 0; i < arrs.length; i++) {
    System.out.print(arrs[i]+" ");//蓉儿 小龙女 过儿
}
//替换
String names2=names.replaceAll("\\w+","  ");
System.out.println(names2);//蓉儿  小龙女  过儿
  • 正则表达式支持爬取信息
String rs="一起学习Java,电话023-123456,或联系邮箱" +
        "123456@qq.com,电话18712345678,023123457" +
        "邮箱JavaNB@qq.com,400-100-1234,4002002314";
//需求:从上面的内容中爬取出电话号码和邮箱。
//1、定义爬取规则,字符串形式
String regex="(\\w{1,30}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,20}){1,2})|(0\\d{2,6}-?\\d{5,20})|(1[3-9]\\d{9})|(400-?\\d{3,9}-?\\d{3,9})";
//2、把这个爬取规则编译成匹配对象。
Pattern pattern = Pattern.compile(regex);
//3、得到一个内容匹配器对象
Matcher matcher = pattern.matcher(rs);
//4、开始找了
while (matcher.find()){
    String rs1 = matcher.group();
    System.out.println(rs1);
}
/*
 找到的结果:
    023-123456
    123456@qq.com
    18712345678
    023123457
    JavaNB@qq.com
    400-100-1234
    4002002314
 */

Arrays类

  • 数组操作工具类,专门用于操作数组元素的。
  • Arrays类的常用API

在这里插入图片描述

//目标:学会使用Arrays类的常用AP工,并理解其原理
int[] arr={10,2,55,23,24,100};
//1、返回数组内容的tostring(数组)
System.out.println(Arrays.toString(arr));//[10, 2, 55, 23, 24, 100]
//2、排序的API(默认自动对数组元素进行升序排序)
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));//[2, 10, 23, 24, 55, 100]
//3、二分搜索技术(前提数组必须排好序才支持,否则出bug)
int index = Arrays.binarySearch(arr, 55);
System.out.println(index);//4
//返回不存在元素的规律: -(应该插入的位置索引 + 1)
int index1 = Arrays.binarySearch(arr, 551);
System.out.println(index1);//-7
//注意:数组如果么有排好序,可能会找不到存在的元素,从而出现bug ! !
int[] arr2={12,36,34,25,13,55,66,44};
System.out.println(Arrays.binarySearch(arr2, 36));//-6
  • Arrays类对于Comparator比较器的支持
  • Arrays类的排序方法:

在这里插入图片描述

  • 自定义排序规则
    • 设置Comparator接口对应的比较器对象,来定制比较规则。

在这里插入图片描述

//目标:自定义数组的排序规则: Comparator比较器对象。
        //1、Arrays 的sort方法对于有值特性的数组是默认升序排序
        int[] ages={34,12,42,23};
        Arrays.sort(ages);
        System.out.println(Arrays.toString(ages));
        //2、需求:降序排序!(自定义比较器对象,只能支持引用类型的排序!! )
        Integer[] age1={34,12,42,23};
        /*
            参数一:被排序的数组必须是引用类型的元素
            参数二:匿名内部类对象,代表了一个比较器对象。
         */
        Arrays.sort(age1, new Comparator() {
            @Override
            public int compare(Integer o1, Integer o2) {
                //制定比较规则
//                if (o1>o2){
//                    return 1;
//                }else if (o1() {
            @Override
            public int compare(Student o1, Student o2) {
                //return o1.getAge()- o2.getAge();//按照年龄升序排序!
                //return o2.getAge()- o1.getAge();//按照年龄降序排序!
                //return Double.compare(o1.getHeight(), o2.getHeight());//比较浮点型可以这样写 升序
                return Double.compare(o2.getHeight(), o1.getHeight());//比较浮点型可以这样写 降序
            }
        });
        System.out.println(Arrays.toString(students));

常见算法

选择排序

在这里插入图片描述

  • 选择排序的思想
    • 每轮选择当前位置,开始找出后面的较小值与该位置交换
  • 选择排序的关键
    • 确定总共需要选择几轮:数组的长度-1
    • 控制每轮从以前位置为基准,与后面元素选择几次。
//1、定义数组
int[] arr={5,1,3,2};
//         0 1 2 3
//2、定义一个循环控制选择几轮: arr.length - 1
for (int i = 0; i < arr.length-1; i++) {
    //i=0  j=1 2 3
    //i=1  j=2 3
    //i=2  j=3
    //3、定义内部循环,控制选择几次
    for (int j = i+1; j < arr.length; j++) {
        //当前位: arr[i]
        //如果有比当前位数据更小的,则交换
        if (arr[i]>arr[j]){
            int temp=arr[i];
            arr[i]=arr[j];
            arr[j]=temp;
        }
    }
}
System.out.println(Arrays.toString(arr));

二分查找(选择排序的改进)

  • 二分查询性能好,二分查找的前提是必须是排好序的数据
  • 二分查找相当于每次去掉一半的查找范围
  • 步骤:
    • 定义变量记录左边和右边位置。
    • 使用while循环控制查询(条件是左边位置<=右边位置)
    • 循环内部获取中间元素索引
    • 判断当前要找的元素如果大于中间元素,左边位置=中间索引+1
    • 判断当前要找的元素如果小于中间元素,右边位置=中间索引-1
    • 判断当前要找的元素如果等于中间元素,返回当前中间元素索引。
public static void main(String[] args) {
    //1、定义数组
    int[] arr={10,14,16,25,28,30,35,88,100};
    System.out.println(binarySearch(arr,25));
}

/**
 * 二分查找算法的实现
 * @param arr  排序的数组
 * @param data 要找的数据
 * @return  索引,如果元素不存在,直接返回-1
 */
public static int binarySearch(int[] arr,int data){
    //1、定义左边位置  和  右边位置
    int left=0;
    int right= arr.length-1;
    //2、开始循环,折半查询。
    while (left<=right){
        //取中间索引
        int middleIndex=(left+right)/2;
        //3、判断当前中间位置的元素和要找的元素的大小情况
        if (data>arr[middleIndex]){
            //往右边找,左位置更新为=中间索引+1
            left=middleIndex+1;
        }else if (data

Lambda表达式

Lambda

  • Lambda表达式是JDK 8开始后的一种新语法形式。
  • 作用:简化匿名内部类的代码写法。
  • Lambda表达式的简化格式:
(匿名内部类被重写方法的形参列表)->{
    被重写方法的方法体代码。
}
注:->是语法形式,无实际含义
  • 注意:Lambda表达式只能简化函数式接口的匿名内部类的写法形式
  • 什么是函数式接口?
    • 首先必须是接口、其次接口中有且仅有一个抽象方法的形式
    • 通常我们会在接口上加上一个@FunctionalInterface注解,标记该接口必须是满足函数式接口。
public class LambdaDemo {
    public static void main(String[] args) {
        //目标:使用Lambda的标准格式简化匿名内部类的代码形式
        //Lambda只能简化接口中只有一个抽象方法的匿名内部类形式

//        Swimming s1 = new Swimming() {
//            @Override
//            public void swim() {
//                System.out.println("老师游泳");
//            }
//        };
        //简化
        Swimming s1=() -> {
            System.out.println("老师游泳");
        };
        go(s1);
        System.out.println("---------------------");
        //继续简化
        go(new Swimming() {
            @Override
            public void swim() {
                System.out.println("老师游泳很开心");
            }
        });
        System.out.println("---------------------");
        //继续继续简化
        go(() ->{
            System.out.println("老师游泳很开心2");
        });
    }
    public static void go(Swimming s){
        System.out.println("开始");
        s.swim();
        System.out.println("结束");
    }
}
@FunctionalInterface //一但加上这个注解必须是函数式接口,里面只能有一个抽象方法
interface Swimming{
    void swim();
}

总结:

  1. Lambda表达式的基本作用?
    • 简化函数式接口的匿名内部类的写法。
  2. Lambda表达式有什么使用前提?
    • 必须是接口的匿名内部类,接口中只能有一个抽象方法
  3. Lambda的好处?
    • Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码,它可以写出更简洁、更灵活的代码,作为一种更紧凑的代码风格,使Java语言表达能力得到了提升。

Lambda简化常见函数式接口

  • Lambda表达式简化Comparator接口的匿名形式

在这里插入图片描述

  • Lambda表达式简化按钮监听器ActionListener的匿名内部类形式

在这里插入图片描述

Lambda省略规则

Lambda表达式的省略写法(进一步在Lambda表达式的基础上继续简化):

  • 参数类型可以省略不写。
  • 如果只有一个参数,参数类型可以省略,同时()也可以省略。
  • 如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,同时要省略分号!
  • 如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写。此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";"不写
//1、Lambda表达式简化Comparator接口的匿名形式
Integer[] age={34,12,42,23};
//源代码
Arrays.sort(age, new Comparator() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o1-o2;//默认升序
    }
});
//简化1
Arrays.sort(age, (Integer o1, Integer o2) ->{
        return o1-o2;
});

//简化2
Arrays.sort(age, (o1, o2) ->{
    return o1-o2;
});

//简化3
Arrays.sort(age, (o1, o2) -> o1-o2);

System.out.println(Arrays.toString(age));
//2、Lambda表达式简化按钮监听器ActionListener的匿名内部类形式
JFrame win=new JFrame("登陆界面");
JButton btn=new JButton("我是一个很大的按钮");
//源代码
btn.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("有人点我,点我");
    }
});
//简化1
btn.addActionListener((ActionEvent e) ->{
        System.out.println("有人点我,点我");
});
//简化2
btn.addActionListener((e) ->{
    System.out.println("有人点我,点我");
});
//简化3
btn.addActionListener(e ->{
    System.out.println("有人点我,点我");
});
//简化4
btn.addActionListener(e ->System.out.println("有人点我,点我"));

win.add(btn);
win.setSize(400,300);
win.setVisible(true);

  1. false,s2创建了两个对象,s1创建了一个对象 ??

  2. false ??

  3. true ??