小黑子—Java从入门到入土过程:第七章

news2024/11/8 20:47:32

Java零基础入门7.0

  • Java系列第七章
    • 1. 游戏打包exe
    • 2. API
      • 2.1 Math
      • 2.2 练习
        • 2.2.1 判断质数
        • 2.2.2 判断水仙花数(自幂数)
      • 2.3 System
      • 2.4 Runtime
      • 2.5 Object
        • 2.5.1 Object 的成员方法
          • (1) toString
          • (2) equals 比较两个对象是否相等
          • (3) clone方法(Object对象中的方法)
        • 2.5.2 Objects
      • 2.6 BigInteger(大的整数)
        • 2.6.1 Biglnteger构造方法:
          • (1) public BigInteger(int num,Random rnd) 获取随机大范围整数
          • (2) public BigInteger(String val) 获取指定的大整数
          • (3) public BigInteger(String val,int radix) 获取指定进制的大整数
          • (4) BigInteger.valueOf(long val)
        • 2.6.2 BigInteger常见成员方法
        • 2.6.3 BigInteger底层存储方式
      • 2.7 BigDecima(大的小数)
        • 2.7.1 Bigdecimal的常见方法
        • 2.7.2 Bigdecimal的底层存储方式
      • 2.7 正则表达式
        • 2.7.1 正则表达式的字符
        • 2.7.2 正则表达式的数量词
        • 2.7.3 正则表达式练习
          • 一、
          • 二、
        • 2.7.4 爬虫
          • 一、带条件的数据爬取
          • 二、贪婪爬取和非贪婪爬取
        • 2.7.5 正则表达式在字符串方法中的使用
        • 2.7.6 分组
          • (1)捕获分组
          • (2)非捕获分组
      • 2.8 JDK7时间
        • 2.8.1 Date 时间

Java系列第七章

1. 游戏打包exe

游戏打包exe要考虑的因素:
在这里插入图片描述
游戏打包核心步骤:
在这里插入图片描述

2. API

2.1 Math

Math是一个帮助我们用于进行数学计算的工具类私有化构造方法,所有的方法都是静态的

在源码中的定义
public final class Math extends Object

即Math是一个最终类,不能被继承

Math是一个帮助计算的工具类 私有化构造方法,所有方法都是静态的
类Math包含用于执行基本数字运算的方法,例如基本指数,对数,平方根和三角函数

Math中的方法基本上都是静态修饰,可以直接通过类名调用
Math. 方法名()
例如:
Math.abs(-11)

常用方法:
在这里插入图片描述

abs的bug

以int为例
int类型的取值范围是-2147483648~2147483647 如果没有正数与负数对应,那么传递负数结果有误

解决方案
使用absExact方法,当取值超过数据类型范围时,会有报错

System.out.println(Math.abs(88));//88
        System.out.println(Math.abs(-88));//88
        System.out.println(Math.absExact(-2147483648));//报错

在这里插入图片描述
ceil 向上取整
在这里插入图片描述

floor 去尾法
在这里插入图片描述
round 四舍五入
在这里插入图片描述
max 获取两个整数的最大值
在这里插入图片描述
min 获取两个整数的最小值
在这里插入图片描述
pow 获取a的b次幂
在这里插入图片描述

sqrt 开方 和 cbrt 开立方
在这里插入图片描述
random 获取随机数
在这里插入图片描述

2.2 练习

2.2.1 判断质数

在这里插入图片描述
但是这样遍历的话,如果要求的数非常大,那么就要从2开始依次遍历,非常麻烦

寻找因子的规律:
在这里插入图片描述
在左边因子当中,必定是小于等于该数(比如16)的平方根的
在右边因子当中,必定是大于等于该数(比如16)的平方根的

在这里插入图片描述
假设两个左右两边的数都是哪怕大于4的一点点,那么就不等于16
同理小于4的一点点时,也不等于
在这里插入图片描述
故其中一个因子当中一定是有小于等于平方根的,还有就是大于等于平方根的
以下因子情况:
在这里插入图片描述

所以判断一个数是否为质数的时候,不需要把所有的数全部遍历一遍,只需要把左边的因子数遍历判断就可以了

代码实现:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        System.out.println("请输入一个整数:");
        Scanner sc = new Scanner(System.in);
        int number = sc.nextInt();
        System.out.println(isPrime(number));
    }

    public static boolean isPrime(int number) {
        int count =0;
        for (int i = 2; i <= Math.sqrt(number); i++) {
            count++;
            if (number % i == 0) {
                return false;
            }
        }
        System.out.println("循环了"+count+"次"+","+number+"是质数");
        return true;
    }
}

在这里插入图片描述

2.2.2 判断水仙花数(自幂数)

在这里插入图片描述

public class Main {
    public static void main(String[] args) {
        int count=0;
        //得到每一个三位数
        for (int i = 100; i < 999; i++) {
            //个位 十位 百位
            int ge =i%10;
            int shi = i/10%10;
            int bai = i/100%10;

            //判断:
            //每一位的三次方之和 跟本身进行比较
            double sum = Math.pow(ge,3)+Math.pow(shi,3)+Math.pow(bai,3);
            if(sum==i){
                count++;
                System.out.println(i);
            }
        }
        System.out.println("循环了"+count+"次");
    }
}

在这里插入图片描述

2.3 System

在这里插入图片描述

计算器机的时间原点:
在这里插入图片描述
currentTimeMillis()来判断程序运行时间
在这里插入图片描述

        long l = System.currentTimeMillis();
        System.out.println(l);
//表示从开始到结束,采用了运行多少时间

arraycopy 数组拷贝

        /*
          第一个参数:数据源,表示被拷贝的数组
          第二个参数:从数据原中的第几个索引开始拷贝
          第三个参数:目的地,我要把数据拷贝到那个数组中
          第四个参数:目的地数组的索引
          第五个参数:拷贝的个数
         */
        System.arraycopy(arr1,0,arr2,2,4);
        for (int i = 0; i < arr2.length; i++) {
            System.out.println(arr2[i]);
        }

在这里插入图片描述
arraycopy的细节:

  • 1.如果数据原数组和目的地数组的值都是基本数据类型,那么两者的类型必须保持一致,否则会报错
  • 2.在拷贝的时候,需要考虑数组的长度,如果超出范围也会报错
  • 3.如果数据原数组和目的地数组的值都是引用数据类型,那么,子类类型可以赋值给父类类型
//Person是Student的父类
Student s1=new Student("zhangsan",18);
Student s2=new Student("sanwu",18);
Student s3=new Student("lisan",18);
Student []arr1={s1,s2,s3};
Person []arr2=new Person[3];
//这里是可以赋值的,但在遍历arr2的时候,要把数据类型再进行转换,换成Student
System.arraycopy(arr1,0,arr2,0,3);
for(i=0;i<arr2.length.i++){
Student stu=(Student)arr2[i];
sout(stu.getname()+" "+stu.getage())

在这里插入图片描述
小结:

在这里插入图片描述

2.4 Runtime

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

主要可以用来监视虚拟机的内存
这个类的方法不是静态的,需要先获取对象才能调用方法

在这里插入图片描述
1.获取Runtime的对象

//获取Runtime对象
        //java的Runtime对象只有一个
        Runtime r1=Runtime.getRuntime();
        Runtime r2=Runtime.getRuntime();
        System.out.println(r1==r2);

在这里插入图片描述

2.exit 停止虚拟机
这个实际上就是System.exit(0)的底层源码

Runtime.getRuntime().exit(0);

3.ailableProcessors 获取cpu线程数

System.out.println(Runtime.getRuntime().availableProcessors());

在这里插入图片描述

4.maxMemory 可以获得的总内存大小,单位byte字节

System.out.println(Runtime.getRuntime().maxMemory()/1024/1024);

在这里插入图片描述

5.totalMemory 已经获得的内存大小,单位byte字节

System.out.println(Runtime.getRuntime().totalMemory()/1024/1024);

在这里插入图片描述

6.freeMemory 虚拟机中剩余内存的大小

System.out.println(Runtime.getRuntime().freeMemory());

在这里插入图片描述
7. 运行cmd命令

        //以字符串的形式运行cmd命令
        //notepad,打开记事本
        //shutdown,关机
        //加上参数才能运行
        //-s,默认一分钟之后关机
        //-s -t 指定关机时间
        //-a 取消关机操作
        //-r 关机并重启
        Runtime.getRuntime().exec("notepad");

2.5 Object

在这里插入图片描述
Object中没有成员变量,所以没有带参构造,只有空参构造方法
public Object

Object 的构造方法
在这里插入图片描述

2.5.1 Object 的成员方法

在这里插入图片描述

(1) toString

返回对象的字符串表现形式

public class Test1 {
    public static void main(String[] args) {
        Object obj = new Object();
        String str1 = obj.toString();
        System.out.println(str1);//java.lang.Object@4eec7777 @之前是包名+类名,@后是对象的地址值
        sout(obj);//打印出来也是java.lang.Object@4eec7777
    }
}

System.out.println(参数)语句的解析
System是类名,out是一个静态变量,System.out:获取被打印的对象,println则是一个方法,参数就表示要打印的内容

核心逻辑:
当我们打印一个对象时,底层会调用对象的toString方法,把对象变成字符串,然后再打印在控制台上,打印完成后换行处理

将toString()打印地址值改成打印对象属性值的解决方案:

重写父类Object中的toString方法

toString方法的结论:

  • 如果打印一个对象,想要看到属性值的话,那么在子类中重写toString方法就行可以了
  • 在重写的方法中,把对象属性值进行拼接返回
    @Override
    public String toString() {
        return name+","+age;
    }

(2) equals 比较两个对象是否相等

在这里插入图片描述

原本比较的是地址值,通过重写(直接用alt+回车的重写)可以比较对象里的属性值

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && name.equals(student.name);
    }
    //测试
        Student stu1=new Student("zhangsan",18);
        Student stu2=new Student("zhangsan",18);
//        System.out.println(stu1);
        boolean s1=stu1.equals(stu2);
        System.out.println(s1);//结果为true

结论:

  1. 如果没有重写equals方法,那么默认使用Object中的方法进行比较,比较的是地址值是否相等
  2. 一般来讲地址值对我们意义不大,所以会进行方法的重写,将equals重写后比较的就是对象内部的属性值了

注:
String类中的equals方法会先判断参数是否为字符串,如果是字符串,再比较内部的属性,但是如果不是字符串,直接返回false
StringBuilder中没有equals方法,所以会直接使用Object中的equals方法,也就是比较地址值是否相等

(3) clone方法(Object对象中的方法)

clone()对象克隆
protected Object clone()
把A对象的属性值完全拷贝给B对象,也叫对象拷贝,对象复制

在这里插入图片描述
在这里插入图片描述

clone()源码,被protected修饰,所以不能直接调用,需要在子类里重写,
ctrl+鼠标点击就可以查看java源码

Cloneable接口

  • 如果一个接口中没有抽象方法
  • 表示当前接口是一个标记性接口
  • 当标记性接口(现在Cloneable表示)一旦实现,那么当前类的对象就可以被克隆
  • 如果没有实现,当前类的对象就不能克隆 即,要想一个对象被克隆的话,就必须实现Cloneable这个接口,然后才能被克隆

alt + 回车 选择第二个异常签名,让克隆不报错
在这里插入图片描述

User类:
import java.util.StringJoiner;

public class User implements Cloneable{//实现额外的接口
    private int id;//游戏角色
    private String username;//用户名
    private String password;//密码
    private String path;//游戏图片
    private int[] data;//游戏进度

    public User() {
    }

    public User(int id, String username, String password, String path, int[] data) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.path = path;
        this.data = data;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public int[] getData() {
        return data;
    }

    public void setData(int[] data) {
        this.data = data;
    }

    public String toString(){
        return "角色编号为:"+id+",用户名 "+username+",密码"+password+",游戏图片"+path+",游戏进度"+arrToString();

    }
    public String arrToString(){
        StringJoiner sj = new StringJoiner(",","[","]");
        for (int i = 0; i < data.length; i++) {
            sj.add(data[i]+"");
        }
        return sj.toString();
    }

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

测试类:
public class ObjectDemo2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        //1.先创建一个对象
        int[] data ={1,2,3,4,5,6,7,8,9};
        User u1 = new User(1,"maghua","12345","girl1",data);

        //2.克隆对象,不能直接克隆
        //因为当前方法是受保护的,表示当前的克隆方法只能被本包的类、还有其他包中的子类所使用
        //又Object是定义再java.lang包下的,不能把代码写再lang包下
        //所以,如果想要clone()方法,只能去User重写克隆方法

        //细节:
        //方法在底层会帮我们创建一个对象,并把原对象中的数据拷贝过去。
        //书写细节:
        //1.重写object中的clone方法
        //2.让javabean类实现cloneable接口
        //3.创建原对象并调用clone就可以了
        User u2 = (User)u1.clone();//由于克隆出来的对象是用户对象,所以要进行强转
        System.out.println(u1);
        System.out.println(u2);

    }
}

在这里插入图片描述
图解:
在这里插入图片描述

Cloneable接口:

package java.lang;
public interface Cloneable {
}

对象克隆方式一:

浅克隆(浅拷贝)
拷贝时,先创建一个新的对象,然后 基本数据类型就拷贝其数值, 引用数据类型就拷贝其地址值
在这里插入图片描述

深克隆(深拷贝)
拷贝时,也会先创建一个新的对象,然后 基本数据类型就拷贝其数值,

  • 引用数据类型在拷贝时,如果是new出来的,就会在堆内存中开辟出一块新的空间,然后把之前老空间里的数据复制到新空间里,再把新空间的新地址值赋值给拷贝的变量,如果不是new出来的,像字符串,数据在串池里的,就会把之前的数据复用
    在这里插入图片描述

实现代码:

上方User类的重写方法修改:
@Override
    protected Object clone() throws CloneNotSupportedException {
        //调用父类中的clone方法
        //相当于让Java帮我们克隆一个对象,并把克隆之后的对象返回出去

        //先把被克隆对象中的数组获取出来
        int[] data = this.data;
        //创建新的数组
        int[] newData = new int[data.length];
        //拷贝数组中的数据
        for (int i = 0; i < data.length; i++) {
            newData[i] = data[i];
        }
        //调用父类中的方法克隆对象
        User u = (User)super.clone();
        //因为父类中的克隆方法是浅克隆,替换克隆出来对象的数组地址值
        u.data = newData;
        return u;
    }

测试类:
		User u2 = (User)u1.clone();

     
        int[] arr =u1.getData();
        arr[0] = 100;
        System.out.println(u1);
        System.out.println(u2);

在这里插入图片描述

以后用到深克隆到实际项目当中时,就会使用第三方的一个工具
使用步骤:

  • 1.先创建一个lib(Library)包,将第三方的工具导入当前项目中
  • 2.编写代码
 //先创建一个工具的对象
        Gson gson=new Gson();
        //把对象变成一个字符串
        String s= gson.toJson(u1);
        User user=gson.fromJson(s,User.class);
        //打印对象
        System.out.println(user);

这个深克隆的工具放到自己了解的路径当中
导入后,再点击添加到库中,如果有问题,看160集
在这里插入图片描述

有问题了看这篇文章

小结:
在这里插入图片描述

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

总结:
在这里插入图片描述

2.5.2 Objects

objects是一个工具类,提供了一些方法去完成一些功能。
在这里插入图片描述

objects的成员方法:
在这里插入图片描述

Studnet s1 = null;
Stundent s2 = new Student("zhangsan",33);
boolean result=Objects.equals(s1,s2);
sout(Objects.isNull(s3));
sout(Objects.nonNull(s4));

直接使用Objects调用
细节:

  • 1.Objects的equals方法的底层会先判断s1是否为null,如果时null,直接返回false
  • 2.如果s1不为null,那么就利用s1再调用equals方法
  • 3.此时的s1为Student类型,所以调用的还是Student的equals方法,如果没有重写,调用的就是Object的equals方法,比较地址值,如果重写了,就会比较属性值。

总结:
在这里插入图片描述

2.6 BigInteger(大的整数)

BigInteger(大的整数):
BigInteger可以表示超出long范围的整数,上限可以看作无限
在这里插入图片描述

2.6.1 Biglnteger构造方法:

在这里插入图片描述

(1) public BigInteger(int num,Random rnd) 获取随机大范围整数

public BigInteger(int num,Random rnd) 获取随机大范围整数

范围[0~2的num次方-1],包含0和2的num次方-1

        Random r = new Random();
        BigInteger bd1 = new BigInteger(4,r);
        System.out.println(bd1);//2^4-1之内出现
(2) public BigInteger(String val) 获取指定的大整数
BigInteger bd2 = new BigInteger("999999999999999999999999999999999999999999999999999999999999999");//照样输出不会报错

BigInteger bd2 = new BigInteger("1.1");//有小数,直接报错

BigInteger bd2 = new BigInteger("abc");//字符串直接报错
(3) public BigInteger(String val,int radix) 获取指定进制的大整数

细节;
1.字符串中的数字必须是整数
2.字符串中的数字必须要跟进制吻合。
比如二进制中,那么只能写0和1,写其他的就报错。

BigInteger bd1=new BigInter("100",10);//这里获取的就是10进制的100,打印出来就是100
BigInteger bd2=new BigInter("100",2);//这里获取的就是2进制的100,打印出来就是4
BigInteger bd3=new BigInter("123",2);//这里代码就会报错,因为二进制中没有2和3
(4) BigInteger.valueOf(long val)

valueOf(long val),BigInteger的静态方法,可以获取BigInteger的对象,内部有优化

BigInteger(String val)与valueOf(long val)的不同之处
先来看相同的地方:他们都是创建一个大整数对象

BigInteger bd1=new BigInteger("100");
BigInteger bd1=BigInteger.valueOf(100);

不同:
1.valueOf能表示的范围比较小,只能在long的范围之内,不能超出long的范围
2.在内部,对常用的数字,-16到16进行了优化,提前把-16到16的BigInteger对象创建好了,多次获取时不会创建新的对象
3.如果超出了范围,就没有优化了,即使相同也会报错

BigInteger bd1=BigInteger.valueOf(16);
BigInteger bd2=BigInteger.valueOf(16);
sout(bd1==bd2);//==号比较的是地址值,结果是true,证明bd1和bd2是同一个对象

BigInteger bd3=BigInteger.valueOf(17);
BigInteger bd4=BigInteger.valueOf(17);
sout(bd3==bd4);//==号比较的是地址值,结果是false,证明bd3和bd4不是同一个对象.
  • 如果不知道数据的范围有多大,就使用BigInteger(String val)
    去获取,如果知道数据的范围在long范围内,就使用valueOf来获取
  • 由于BigInteger对象一旦创建,内部记录的值就不能发生改变,所以,只要进行计算,像加减乘除在内的计算都会产生一个新的BigInteger对象

小结:
在这里插入图片描述

2.6.2 BigInteger常见成员方法

在这里插入图片描述
因为BigInteger是一个对象,不能直接相加减,要通过方法来完成
一些方法的使用:

import java.math.BigInteger;

public class BigIntegerTest {
    public static void main(String[] args) {
        BigInteger bd1=BigInteger.valueOf(15);
        BigInteger bd2=BigInteger.valueOf(5);
        //加
        BigInteger bd3=bd1.add(bd2);
        System.out.println(bd3);
        
        //减
        BigInteger bd4=bd1.subtract(bd2);
        System.out.println(bd4);
        
        //乘
        BigInteger bd5=bd1.multiply(bd2);
        System.out.println(bd5);
        
        //除
        BigInteger bd6=bd1.divide(bd2);
        System.out.println(bd6);
        
        //除,获取商的同时获取余数 
        //返回值是一个数组,第一个值记录商,第二个值记录余数
        BigInteger[] bd7=bd1.divideAndRemainder(bd2);
        System.out.println(bd7);
        System.out.println(bd7[0]);
        System.out.println(bd7[1]);
        //比较是否相同
        Boolean a=bd1.equals(bd2);
        System.out.println(a);
        
        //次幂
        BigInteger bd9=bd1.pow(3);
        BigInteger bd10=bd2.pow(3);
        System.out.println(bd9+ " "+bd10);
        
        //返回较大值
        BigInteger bd11=bd1.max(bd2);
        System.out.println(bd11);
        
        //返回较小值
        BigInteger bd12=bd1.min(bd2);
        System.out.println(bd12);
        
        //转换类型
        int b=bd1.intValue();
        System.out.println(b);
    }
}

2.6.3 BigInteger底层存储方式

在这里插入图片描述
在这里插入图片描述

就是将一个大的整数分成多段存入数组中
1.先将数转化成补码
2.将补码32位分成一段,然后分成多段
3.再将多段补码转化为多段十进制整数
4.再将十进制整数存入数组

数组的最大长度就是int的最大值:2147483647(理论值)
在这里插入图片描述

总结:
在这里插入图片描述

2.7 BigDecima(大的小数)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

计算机中的小数的存储方式
由于小数在计算机中用二进制表示时会很多,而每一种数据类型能够占用的空间是有限的,所以就会导致小数在计算机中的存储是不精确的

在实际应用中:
在这里插入图片描述

BigDecimal的作用:

  • 用于小数的精确计算
  • 用很大的小数

BigDecimal的一些构造方法:

方法名说明
public BigDecimal(double val)将 double 转换为 BigDecimal,但是,此构造方法的结果有一定的不可预知性,即还是有可能是不精确的,所以不推荐使用
public BigDecimal(String val)将字符串转换为 BigDecimal。,它不会遇到 BigDecimal(double) 构造方法的不可预知问题。

与BigInteger一样,BigDecimal也有valueOf(long val)的静态方法,可以获取BigDecimal的对象,可以传递整数。

import java.math.BigDecimal;

public class BigDecimalTest {
    public static void main(String[] args) {
        //通过传递double类型的小数来创建对象
        //这种方式有可能不精确,不推荐使用
        BigDecimal bd1=new BigDecimal(0.01);
        BigDecimal bd2=new BigDecimal(0.09);
        System.out.println(bd1);
        System.out.println(bd2);
        //结果为
        //0.01000000000000000020816681711721685132943093776702880859375
        //0.0899999999999999966693309261245303787291049957275390625


        //通过传递字符串表示的小数来创建对象
		//常用的方式1
        BigDecimal bd3=new BigDecimal("0.01");
        BigDecimal bd4=new BigDecimal("0.09");
        System.out.println(bd3);
        System.out.println(bd4);
        //结果为
        //0.01
        //0.09
        
		//通过静态方法获取对象
        BigDecimal bd6 = BigDecimal.valueOf(10);
        BigDecimal bd7 = BigDecimal.valueOf(10);
        System.out.println(bd6 == bd7);//true

        BigDecimal bd6 = BigDecimal.valueOf(10.0);
        BigDecimal bd7 = BigDecimal.valueOf(10.0);
        System.out.println(bd6 == bd7);//false
		
    }
}

通过传递字符串表示的小数来创建对象valueOf静态方法的差别

  1. 如果表示的数字没有超出double的取值范围,推荐使用静态方法
  2. 如果要表示的数字比较大,超出了double的取值范围,建议使用构造方法
  3. 在静态方法中,如果传递的是0~10之间的整数(包括0和10),那么,方法会返回已经创建好的对象,不会重新new,跟BigInteger是一样的原理,但是,如果传递的是小数的话,就不会有优化,会创建新的对象

2.7.1 Bigdecimal的常见方法

在这里插入图片描述

//前面几个跟BigInteger没什么差别
//主要是除法
        BigDecimal bd1 = BigDecimal.valueOf(10.0);
        BigDecimal bd2 = BigDecimal.valueOf(3.0);
        //除法
        BigDecimal bd6 = bd1.divide(bd2);
        System.out.println(bd6);//报错
//当除不尽时,public BigDecimal divide(BigDecimal val)这个方法就会报错,
//此时,就要使用
//public BigDecimal divide(BigDecimal val,精确几位,舍入模式)。这个方法
        BigDecimal bd6 = bd1.divide(bd2,2,BigDecimal.ROUND_HALF_UP);
        System.out.println(bd6);//结果为3.33

其他的舍入模式可以在api文档中的RoundingMode类中可以找到:

数轴表示:

在这里插入图片描述

2.7.2 Bigdecimal的底层存储方式

在这里插入图片描述

Bigdecimal会先得到字符串里的字符,将字符串分成一个个单独的字符,在将字符转化为ascll码表上的数值,再存储到数组里。

例如:
在这里插入图片描述
总结:
在这里插入图片描述

2.7 正则表达式

正则表达式用于校验字符串的相关操作,可以很方便
字符串通过使用matches方法来匹配相应的正则表达式
"abc".matches("[bcd]");//结果为false

练习:
在这里插入图片描述

public static void main(String[] args) {
        //规则:6位及20位之内,0不能在开头,必须全部是数字
        //一个编程思想:
        // 先把异常数据进行过滤,
        // 过滤后得到的就是满足要求的数据了
        String qq = "1234567890";
        //System.out.println(checkQQ(qq));但是这样写就稍微麻烦了
        System.out.println(qq.matches("[1-9]\\d{5,19}"));//[5,19]表示6位到20位
    }

    public static boolean checkQQ(String qq){
        int len =qq.length();
        if(len<6||len>20){
            return false;
        }
        //0不能在开头
        if(qq.startsWith("0")){
            return false;
        }
        //必须全部是数字
        for (int i = 0; i < qq.length(); i++) {
            char c = qq.charAt(i);
            if(c<'0'||c>'9'){
                return false;
            }
        }
        return true;
    }
}

在这里插入图片描述
正则表达式的作用:

  • 1.校验字符串是否满足规则
  • 2.在一段文本中查找满足要求的内容

在这里插入图片描述

2.7.1 正则表达式的字符

在这里插入图片描述
上面的方括号([ ]) 在正则表达式中表示一个字符的范围,字符串里出现的字符一定要在这个范围之内,不在范围之内的话会返回false

  • ^在正则表达式中表示取反的意思
  • &&在正则表达式中表示取交集的意思
  • ()是分组
  • |在方括号外表示并集

在java中,\表示转义字符,改变后面那个字符原本的含义
sout(" \" ")打印出来的就是,sout(" " ")这样写会报错

\\就表示一个普通的\符号,不表示转义字符

1.字符类例子:

取值判断
sout("a".metches("[abc]"));//true
sout("ab".metches("[abc]"));//false,因为这里的正则表达式只能表示一个字符的范围
//,如果想表示两个字符的范围的话,可以这样写
sout("ab".metches("[abc][abc]"));//这样才可以表示两个字符

取反
sout("a".metches("[^abc]");//false
sout("d".metches("[^abc]");//true
sout("zz".metches("[^abc]"));//false
sout("zz".metches("[^abc][^abc]"));//false

a-z A-Z(包括头尾的范围)
sout("a".metches("[a-zA-Z]");//true
sout("z".metches("[a-zA-Z]");//true
sout("aa".metches("[a-zA-Z]");//false
sout("zz".metches("[a-zA-Z]");//false
sout("zz".metches("[a-zA-Z][a-zA-Z]");//true
sout("0".metches("[a-zA-Z0-9]");//ture

[a-d[m-p]]: a到d,或m到p
sout("a".metches("[a-d[m-p]]");//true
sout("d".metches("[a-d[m-p]]");//true
sout("m".metches("[a-d[m-p]]");//true
sout("p".metches("[a-d[m-p]]");//true
sout("e".metches("[a-d[m-p]]");//false

[a-z&&[def]]: a-z和def的交集。为: d, e, f
//如果要求两个范围的交集,那么需要写符号&&
//这里如果只写了一个&,那么就不表示为一个交集了,就是单纯的一个&符号,没有任何含义
sout("a".metches("[a-z&&[def]]");//false
sout("a".metches("[a-z&[def]]");//true
sout("d".metches("[a-z&&[def]]");//true
sout("&".metches("[a-z&[def]]");//true
sout("0".metches("[a-z&[def]]");//false

[a-z&&[^bc]:a-z和非bc的交集。(等同于[ad-z])
sout("a".metches("[a-z&&[^bc]");//ture
sout("b".metches("[a-z&&[^bc]");//false
sout("0".metches("[a-z&&[^bc]");//false

[a-z&&[^m-p]:a到z和除了m到p的交集。(等同于[a-lq-z])
sout("a".metches("[a-z&&[^m-p]");//true
sout("m".metches("[a-z&&[^m-p]");//false
sout("0".metches("[a-z&&[^m-p]");//false

2.预定义字符类:

.表示任意一个字符
sout("你".metches(".."))//false,因为有两个. ,所以需要两个字符
sout("你是".metches(".."))//true,
sout("你".metches("."))//true

\\d
因为\是转义字符,所以用\\来表示一个普通的\,则\\d就表示\d,而\d表示任意的一个数字
// 简单来记: 两个\表示一个\
sout("0".metches("\\d"))//true
sout("n".metches("\\d"))//false
sout("21".metches("\\d"))//false
sout("21".metches("\\d\\d"))//true

\\D
sout("n".metches("\\D"))//true
sout("1".metches("\\D"))//false

\\w 只能是一位单词字符[a-zA-Z_0-9]
sout("n".metches("\\w"))//true
sout("_".metches("\\w"))//true
sout("8".metches("\\w"))//true
sout("你".metches("\\w"))//false

\\W 非单词字符
sout("n".metches("\\W"))//false
sout("_".metches("\\W"))//false
sout("0".metches("\\W"))//false
sout("你".metches("\\W"))//true

2.7.2 正则表达式的数量词

正则表达式的数量词,可以一次表示多个字符
在这里插入图片描述

// x{6,} 至少出现6位
sout("234jnhs".matches("\\w{6,}"));//true
sout("23sx".matches("\\w{6,}"));//false

//x{4}必须是4位
sout("3424".matches("[a-zA-Z0-9]{4}"))//true
sout("3A424".matches("[a-zA-Z0-9]{4}"))//false

忘记的可以看api文档Pattern

2.7.3 正则表达式练习

一、

在这里插入图片描述

public static void main(String[] args) {
        //细节:
        //拿着一个正确的数据,从做到右依次去写
        //13112345678

        //分成三部分:
        //第一部分:1表示手机号码只能以1开头
        //第二部分:[3-9]表示手机号码第二位只能是3-9之间的
        //第三部分: \\d{9}表示任意数字可以出现9次,也只能出现9次
        String regex1 = "1[3-9]\\d{9}";
        System.out.println("13112345678".matches(regex1));
        System.out.println("131".matches(regex1));
        System.out.println("------------------------------------------");

        //座机号码
        //020-2324242 02122442 027-42424 0712-3242434
        //思路:
        //在书写座机号正则的时候需要把正确的数据分为三部分
        //一:区号 0\\d{2,3}
        //         0:表示区号一定是以0开头的
        //         \\d{2,3}:表示区号从第二位开始可以是任意的数字,可以出现2到3次
        //二:-   ?表示次数,0或一次
        //三:号码  号码的第一位也不能以0开头,从第二位开始可以是任意的数字,号码的总长度:5-10位
        String regex2 = "0\\d{2,3}-?[1-9]\\d{4,9}";
        System.out.println("020-2324242".matches(regex2));
        System.out.println("0712-3242434".matches(regex2));
        System.out.println("------------------------------------------");

        //邮箱号码
        //3232323@qq.com zhangsan@itcast.cnn dleieee9@163.com dleieees@pci.com.cn
        //思路:
        //在书写邮箱号码正则的时候需要把正确的数据分为三部分
        //第一部分:@的左边 \\w+,一个非单词字符串出现多次
        //任意的字母数字下划线,至少出现一次就可以了
        //第二部分:@ 只能出现一次
        //第三部分: . 的左边可以是字符也可以是数字 [\\w&&[^_]]{2,6}
        //               任意的字母加数字,总共出现2-6次(此时不能出现下划线)
        //           .      \\.
        //           大写字母,小写字母都可以,只能出现2-3次[a-zA-Z]{2,3)
        String regex3 = "\\w+@[\\w&&[^_]]{2,6}(\\.[a-zA-Z]{2,3}){1,2}";
        System.out.println("3232323@qq.com".matches(regex3));
        System.out.println("dleieees@pci.com.cn".matches(regex3));

    }

在这里插入图片描述

在实际开发中,使用anyrule插件可以快捷创建正则表达式

右键点击
在这里插入图片描述
在这里插入图片描述

根据时间需求,把开头和末尾的符号删掉
String regex4="(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d";
作为区分

        //24小时的正则表达式 23:11:11
        String regex4 = "([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d";
        System.out.println("23:11:11".matches(regex4));//true

        //优化
        String regex5 = "([01]\\d|2[0-3])(:[0-5]\\d){2}";
        System.out.println("23:11:11".matches(regex5));//true
二、

在这里插入图片描述

public static void main(String[] args) {
        //用户名要求:大小写字母,数字,下划线一共4-16位
        String regex1 = "\\w{4,16}";
        System.out.println("magua".matches(regex1));
        System.out.println("------------------------------------------");

        //身份证号码的简单校验:
        //18位,前17位任意数字,最后一位可以是数字可以是大写或小写的x
        String regex2 = "[1-9]\\d{16}(\\d|X|x)";
        System.out.println("41080119930228457x".matches(regex2));
        //另类写法方式一
        String regex3 = "[1-9]\\d{16}[\\dXx]";
        System.out.println("510881197609822309".matches(regex3));
        System.out.println("------------------------------------------");

        //忽略大小写的书写方式
        //在匹配的时候忽略abc的大小写
        //方式二
        String regex4 = "a((?i)b)c";//表示只忽略a后面b的大小写
        System.out.println("abc".matches(regex4));//true
        System.out.println("ABC".matches(regex4));
        System.out.println("aBc".matches(regex4));
        System.out.println("------------------------------------------");

        //方式三
        String regex5 = "[1-9]\\d{16}(\\d|(?i)x)";
        System.out.println("15040119810705387X".matches(regex5));
        System.out.println("------------------------------------------");

        //身份证号码的严格校验
        //4108011993 02 28 457x
        //前面6位:省份,市区,派出所等信息﹑第一位不能是0,后面5位是任意数字  [1-9]\\d{5}
        //年的前半段:18 19 20                                               (18|19|20)
        //年的后半段:任意数字出现两次                                        \\d{2}
        //月份: 01 ~ 09      10 11 12                                       (0[1-9]|1[0-2])
        //日期:  01 ~ 31  10~19 20~29 30 31                                 (0[1-9]|[12]\\d|3[01])
        //后面四位:
        //任意数字出现3次最后一位可以是数字也可以是大写x或者小写x             \\d{3}[\\dXx]

        //编写正则的小心得:
        //第一步:按照正确的数据进行拆分
        //第二步:找每一部分的规律,并编写正则表达式
        //第三步:把每一部分的正则拼接在一起,就是最终的结果书写的时候:从左到右去书写。
        String regex6 = "[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]";
        String regex7 = "[1-9]\\d{5}(18|19|20)\\d{2}(0\\d|10|11|12)(0[1-9]|[1-2]\\d|30|31)\\d{3}[\\dXx]";
        System.out.println("41080119930228457x".matches(regex6));
        System.out.println("41080119930228457x".matches(regex7));
    }

在这里插入图片描述

小结(一些符号的作用):
在这里插入图片描述
在这里插入图片描述

2.7.4 爬虫

爬虫即在一段文本中查找满足的内容

使用的两个类:

  • Pattern:表示正则表达式

获取正则表达式的对象:

通过Pattern的静态方法complie获取正则表达式的对象
Pattern p=Pattern.compile(“Java\d{0,2}”);

  • Matcher:文本匹配器,作用按照正则表达式的规则去读取字符串,从头开始读取,在大字符串中去找符合匹配规则的字串

1.通过Matcher获取文本匹配器的对象 Matcher m=p.matcher(str);(用m读取str,按照p的规则找里面的小串)

2.通过循环获取每一个满足条件的值,循环里通过Matcher的group方法获取具体字符串,循环的条件是由Matcher对象的find方法来判断循环是否停止

练习1:
在这里插入图片描述

ctrl + alt + m 快捷键 选中内容快捷包含生成一个方法

import java.util.regex.Matcher;
import java.util.regex.Pattern;
public static void main(String[] args) {
 String str = "Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11,"+
                "因为这两个是长期支持版木,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";

        
        //获取正则表达式的对象
        Pattern p = Pattern.compile("Java\\d{0,2}");
        //通过Pattern的静态方法complie获取正则表达式的对象


        //获取文本匹配器的对象
        //m:文本匹配器的对象
        //str:大串
        //p:规则
        //解释:m要在str中找符合p规则的小串
        Matcher m = p.matcher(str);

        //拿着文本匹配器从头开始读取,寻找是否有满足规则的子串
        //如果没有,方法返回false
        //如果有,返回true,在底层记录字串的起始索引喝结束索引+1
        //0,4
        boolean b = m.find();

        //方法底层会根据find方法记录的索引进行字符串的截取
        //subString(起始索引,结束索引);包头不包尾
        //(0,4)但是不包含4索引
        //会把截取的小串进行返回
        String s1 = m.group();
        System.out.println(s1);

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

        //第二次调用group方法的时候,会根据find方法记录的索引再次截取子串
        String s2 = m.group();
        System.out.println(s2
        );
    }

在这里插入图片描述

但是,这样写有个弊端,就是不能找到所有符合p正则条件的

修改:

 String str = "Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11,"+
                "因为这两个是长期支持版木,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";


        //method1(str);

        //1.获取正则表达式的对象
        Pattern p = Pattern.compile("Java\\d{0,2}");
        //2.获取文本匹配器的对象
        //拿着m去读取str,找到符合p规则的字符
        Matcher m = p.matcher(str);

        //3.利用循环获取所以符合p规则的
        while(m.find()){
            String s = m.group();
            System.out.println(s);
        }

在这里插入图片描述
练习2:
在这里插入图片描述

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexDemo1 {
    public static void main(String[] args) {
        /*
          手机号正则表达式:1[3-9]\d{9}
          邮箱正则表达式:\w+@[\w&&[^_]]{2,6}(\.[a-zA-Z]{2,3}}){1,2}
          座机电话表达式:0\d{2,3}-?[1-9]\d{4,9}
          热线电话表达式:400-?[1-9]\\d{2}-?[1-9]\\d{3}
        */

        String s ="来黑马程序员学习Java, "+
                "电话:18512516758,18512508907"+
                "或者联系邮箱: boniu@itcast.cn, " +
                "座机电话: 01036517895,010-98951256"+
                "邮箱: bozai@itcast.cn," +
                "热线电话: 400-618-9090 , 400-618-4080,4006184008,4006189090";
        String regex = "(1[3-9]\\d{9})" +
                "|(\\w+@[\\w&&[^_]]{2,6}(\\.[a-zA-Z]{2,3}}){1,2})" +
                "|(0\\d{2,3}-?[1-9]\\d{4,9})" +
                "|(400-?[1-9]\\d{2}-?[1-9]\\d{3})";

        //1.获取正则表达式的对象
        Pattern p = Pattern.compile(regex);
        //2.获取文本匹配器的对象
        //利用m去读取s,会按照p的规则找里面的小串
        Matcher m = p.matcher(s);

        //3.利用循环获取每一个数据
        while (m.find()){
            String str = m.group();
            System.out.println(str);
        }


    }


}

在这里插入图片描述

一、带条件的数据爬取

在这里插入图片描述

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        String s="Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11," +
                "因为这两个是长期支持版本,下一个长期支持版木是Java17,相信在未来不久Java17也会逐渐登上历史舞台";

        //1.定义正则表达式
        //?理解位前面的数据Java
        //=表示在Java后面要跟随的数据
        //但是在获取的时候,只获取前半部分
        //需求1:
        String regex1 = "((?i)Java)(?=8|11|17)";
        //需求2:
        String regex2 = "((?i)Java)(8|11|17)";
        String regex3 = "((?i)Java)(?:8|11|17)";//?:同样表示2的效果,选取中有的
        //需求3:
        String regex4 = "((?i)Java)(?!8|11|17)";

        Pattern p = Pattern.compile(regex1);
        Matcher m = p.matcher(s);
        while (m.find()){
            System.out.println(m.group());
        }
    }

}

在这里插入图片描述

二、贪婪爬取和非贪婪爬取
  1. 贪婪爬取:在爬取时,尽可能多的爬取数据
  2. 非贪婪爬取:尽可能少爬取数据
    在这里插入图片描述

Java默认为贪婪爬取
如果我们在数量词+ *后加上问号,那么此时就是非贪婪爬取
在这里插入图片描述

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        String s="Java自从95年问世以来,abbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaa" +
                "经历了很多版本,目前企业中用的最多的是Java8和Java11," +
                "因为这两个是长期支持版本,下一个长期支持版木是Java17,相信在未来不久Java17也会逐渐登上历史舞台";

        String regex1 = "ab+?";
        String regex2 = "ab+";
        Pattern p1 = Pattern.compile(regex1);
        Matcher m1 = p1.matcher(s);
        Pattern p2 = Pattern.compile(regex2);
        Matcher m2 = p2.matcher(s);

        while(m1.find()){
            System.out.println(m1.group());
        }
        while(m2.find()){
            System.out.println(m2.group());
        }
    }

}

在这里插入图片描述

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

在这里插入图片描述
如果说字符串方法的形参名字为regex,那么就能识别正则表达式
在这里插入图片描述
练习:

public static void main(String[] args) {
        String s="小实时jasndjasnoid1231小淡淡ndasjkldnan213131小灰灰";
        //细节:
        //方法在底层跟之前一样也会创建文本解析器的对象
        //然后从头开始去读取字符串的内容,只要有满足的,那么久用第二个参数去替换
        String result = s.replaceAll("[\\w&&[^_]]+","vs");
        System.out.println(result);

        String[] arr = s.split("[\\w&&[^_]]+");
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }

在这里插入图片描述

2.7.6 分组

分组就是一个小括号

与数学的计算相似
在正则表达式中,\\x(组号)就表示把第x组的数据再拿出来用一次

每组是有组号的 ,也就是序号

  • 规则1;从1开始,连续不间断
  • 规则2;以左括号为基准,最左边的是第一组,其次为第二组,依次类推
    在这里插入图片描述
(1)捕获分组

练习1:
在这里插入图片描述

    public static void main(String[] args) {
        //a123a b2324b c1234c d2131a(false)
        String regex1="(.).+\\1";
        //  (.)表示首字符可以是任意的
        //  .+表示在该中间是任意的
        //  \\1 表示把第1组的内容再拿出来用一次,也就是(.)里面的首字母,再后面也必须要相同
        System.out.println("a123a".matches(regex1));
        System.out.println("b2324b".matches(regex1));
        System.out.println("c1234c".matches(regex1));
        System.out.println("d2131a".matches(regex1));
        System.out.println("——————————————————————————————————————————————————");

        //abc213abc
        String regex2="(.+).+\\1";
        //  (.+)表示任意一个字符至少出现一次
        System.out.println("abc123abc".matches(regex2));
        System.out.println("bc2324bc".matches(regex2));
        System.out.println("csx1234csx".matches(regex2));
        System.out.println("dz2131ac".matches(regex2));
        System.out.println("——————————————————————————————————————————————————");

        //aaa123aaa
        //括起来两个括号之后,表示两组,\\1 就要变成 \\2了
        //这里的\\2:把第2组再拿出来再使用
        // *: 作用于\\2,表示是后面重复的内容出现0次或多次
        // 大括号的一个整体,后面的\\1表示拿出来一个整体用
        String regex3="((.)\\2*).+\\1";
        System.out.println("aaa123aaa".matches(regex3));
        System.out.println("aaa123aab".matches(regex3));
    }

在这里插入图片描述
在这里插入图片描述
练习2:
在这里插入图片描述

 public static void main(String[] args) {
        String str="我要学学编编编编编编编编程程程程程程程程程程程";

        //需求:把重复的内容替换为单个的学学
        //学学         学
        //编编编编      编
        //程程程程程程   程
        //(.)   表示把重复内容的第一个字符看作第一组
        // \\1  表示第一个字符再次出现
        // +   表示至少一次
        // $1  表示把正则表达式中第一组的内容,再拿出来用
        String result = str.replaceAll("(.)\\1+","$1");
        System.out.println(result);
    }

在这里插入图片描述

(2)非捕获分组

分组之后不需要再用本组数据,仅仅是把数据括起来,不占用组号,不能用\\组号来使用非捕获

在这里插入图片描述
上述表格就的具体案例就在带条件的数据爬取

在这里插入图片描述
小结:
在这里插入图片描述

2.8 JDK7时间

JDK7时间有三个类
Date:时间类
SimpleDateFormat: 格式化时间类
在这里插入图片描述

Calender: 日历类

2.8.1 Date 时间

时间的相关知识
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Date的常用方法:

方法名作用
public Date()创建Date对象,表示当前时间
public Date(long date)创建Date对象,表示指定时间
public void setTime(long time)设置/修改毫秒值
public long getTime获取时间对象的毫秒值

展示:
注意导包一定要点java.lang的
在这里插入图片描述

    public static void main(String[] args) {
        //1.创建对象表示一个时间
        Date d1 = new Date();
        System.out.println(d1);

        //2.创建对象表示一个指定的时间
        Date d2 = new Date(0L);//对于long类型的,可以加个L
        System.out.println(d2);//表示从时间原点开始过了0毫秒

        //3.setTime 修改时间
        d2.setTime(1000L);
        System.out.println(d2);//在时间原点上过了1000毫秒,也就是1秒

        //4.getTime获取当前时间的毫秒值
        long time = d2.getTime();//在左边基础上 ctrl + alt + v
        System.out.println(time);

    }

在这里插入图片描述
练习:
在这里插入图片描述

public static void main(String[] args) {
        Random r=new Random();
        //创建两个时间对象
        Date d2=new Date(Math.abs(r.nextInt()));
        Date d3=new Date(Math.abs(r.nextInt()));
        long time1 = d2.getTime();
        long time2 = d3.getTime();

        if(time1>time2){
            System.out.println("第一个时间在后面,第二个时间在前面");
        }else if(d2.getTime()< d3.getTime()){
            System.out.println("第二个时间在后面,第一个时间在前面");
        }else{
            System.out.println("表示两个时间一样");
        }

        method1();
    }

    private static void method1() {
        //1.创建一个对象,表示时间原点
        Date d1=new Date(0L);

        //2.获取的时间的毫秒值
        long time=d1.getTime();
        //3.在这个基础上我们要加一年的毫秒值即可
        time=time+1000L*60*60*24*365;

        //4.把计算之后的时间毫秒值,再设置回d1当中
        d1.setTime(time);
        System.out.println(d1);
    }

在这里插入图片描述
小结:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/420855.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

投放视频广告时,如何快速与第三方播放器兼容?

新媒体时代&#xff0c;广告样式越来越丰富。相较于传统的图文信息&#xff0c;视频类广告更具有直观性&#xff0c;能够让消费者在了解产品知识和功能的同时加深对产品的印象。 因此在各类网站或App上投放视频类广告是个很好的宣传方式&#xff0c;但广告商们如果想在网站上展…

1.14 从0开始学习Unity游戏开发--物理引擎

上一篇文章我们讲了如何动态创建物体&#xff0c;以及如何用Prefab机制复用我们制作好的物体和逻辑&#xff0c;那么本篇我们将会讲解如何利用这些功能&#xff0c;结合Unity自带的物理引擎&#xff0c;实现一个简单的FPS游戏的效果。 物理组件 首先我们需要先了解如何使用Un…

Linux基础(超级无敌认真好用,万字收藏篇!!!!)

文章目录Linux基础1 Linux概述1.1 Linux特点1.2 Linux和Window区别2 Linux安装2.1 什么是虚拟化2.2 安装虚拟机2.3 配置网络环境3 Linux文件目录4 Linux常用命令4.1 文件与目录操作4.2 查看文件内容4.3 文本内容处理4.4 查询操作4.5 网络相关4.6 其他命令4.7 解压缩命令5 VI/VI…

今天面了个腾讯拿 38K 出来的,让我见识到了基础的天花板

今天上班开早会就是新人见面仪式&#xff0c;听说来了个很厉害的大佬&#xff0c;年纪还不大&#xff0c;是上家公司离职过来的&#xff0c;薪资已经达到中高等水平&#xff0c;很多人都好奇不已&#xff0c;能拿到这个薪资应该人不简单&#xff0c;果然&#xff0c;自我介绍的…

0102加权quick_union和路径压缩-union-find-动态连通性-算法研究

3 union-find算法 3.5 加权quick-union算法 3.5.1 算法实现 quick-union出现最坏情况&#xff0c;因为我们是随意将一棵树链接到另外一棵树上&#xff0c;修改如下&#xff1a; 添加一个数组和一些代码记录树中节点数&#xff1b;链接时将节点数较小的树链接到较大的树上&a…

基础算法-双指针,滑动窗口,位运算,区间离散化

双指针 两种类型 for(int i0,j0;i<n;i) {while(i<j&&check(i,j)) j;// 每道题目具体逻辑}双指针最核心的性质 可以优化 输入一个字符串 把每个单词输出出来 i找到单词开头 j找到空格 vector<string> rs; for(int i0,j0;i<s.size();i) {ji;while(j&…

.Net Forms Resize 12 Crack

.Net Forms Resize 12 Crack 添加了对Microsoft Visual Studio 2022(v17.5.3)及更高版本的支持。 增加了对Microsoft Windows Server 2019和2022的支持。 改进并调整引擎大小(大约快20%)。 更新与受支持的第三方控件的新版本的兼容性。 添加了新的Microsoft Framework 4.8.1库。…

in、not in、between and、基本查询数据库实验三 单表查询(一)(头歌实践教学平台)

文章目的初衷是希望学习笔记分享给更多的伙伴&#xff0c;并无盈利目的&#xff0c;尊重版权&#xff0c;如有侵犯&#xff0c;请官方工作人员联系博主谢谢。 目录 第1关&#xff1a;基本查询语句 任务描述 相关知识 查询数据表中指定字段的内容 查询数据表中的所有内容 …

Ucore lab2

练习一&#xff1a;实现first-fit 连续物理内存分配算法 根据实验指导书中的实验执行流程概述&#xff0c;先了解分析ucore如何对物理内存进行管理&#xff0c;再完成实验练习。 在对物理内存进行管理之前&#xff0c;需要先进行物理内存布局的探测&#xff0c;探测得到的内存…

[LeetCode解题报告] 1157. 子数组中占绝大多数的元素

[LeetCode解题报告] 1157. 子数组中占绝大多数的元素 一、 题目1. 题目描述2. 原题链接二、 解题报告1. 思路分析2. 复杂度分析3. 代码实现三、 本题小结四、 参考链接一、 题目 1. 题目描述 2. 原题链接 链接: 1157. 子数组中占绝大多数的元素 二、 解题报告 1. 思路分析 …

python+requests的接口自动化测试框架实例详解教程

目录 前言 一、环境准备 二、设计框架结构 三、实现框架功能 四、执行测试用例 五、总结 前言 Python是一种简单易学、功能强大的编程语言&#xff0c;广泛应用于各种软件开发和测试场景中。requests是Python中流行的HTTP库&#xff0c;支持发送HTTP请求和处理HTTP响应&a…

【c语言】多维数组原理

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 给大家跳段街舞感谢支持&#xff01;ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ…

话说~~ HTTP协议请求的工作流程 (Web服务请求过程)最细详解

目录 文章导入 &#xff1a; 概述 &#xff1a; 详解过程 &#xff1a; DNS域名解析 &#xff1a; DNS 域名解析过程分析 &#xff1a; TCP连接搭建 &#xff1a; 等待TCP队列 建立TCP连接 发起 HTTP 请求 &#xff1a; # 哪是如何进行 HTTP 请求的呢 &#…

实验架构的部署

目录 实验要求 实验环境 1、部署静态页面 2、部署负载均衡 3、搭建动态网页 4、 nginx反向代理 5、部署NFS 7、mysql 安装mysql 安装mha 准备主从复制 开启mha 架构的部署 实验要求 完成用户访问时虚拟IP由LVS负责高可用&#xff0c;静态交给nginx处理&#xff0c;…

【工具篇】Spring Boot 整合阿里云短信-SMS

短信服务-SMS 短信服务&#xff08;Short Message Service&#xff09;是广大企业客户快速触达手机用户所优选使用的通信能力&#xff0c;分为国内短信服务和国际/港澳台短信服务。通过 API/SDK、控制台调用短信发送能力&#xff0c;将指定信息发送至国内或境外手机号码。 应…

<数据结构>NO1.算法的时空复杂度

文章目录&#x1f6a9;算法效率算法复杂度&#x1fa85;时间复杂度大O的渐进表示法常见的时间复杂度举例&#x1fa85;空间复杂度大O的渐进表示法常见的空间复杂度举例&#x1f5ef;️常见复杂度对比&#x1f5ef;️&#x1f6a9;算法效率 算法是一个被设计好的&#xff0c;计…

python 读写txt方法

​​​​​​​ 1. Python支持在程序中读写 txt文件。这里有两种方式&#xff1a; 方式一&#xff1a;使用 python内置函数&#xff0c;该函数将一个字符串的长度转换为与这个字符串长度相关的值。 例如&#xff1a;" readme"&#xff08;"r&#xff09;。 prin…

数据结构---递归转化为非递归

递归转化为非递归前言快速排序非递归归并排序的非递归前言 为什么要学习非递归写法呢&#xff1f; 当我们在用递归实现一个程序的时候&#xff0c;要考虑一个问题&#xff0c;这个程序用递归去实现&#xff0c;当数据量庞大的时候&#xff0c;会不会造成栈溢出(STACK OVERFLOW…

学习风`宇blog的websocket模块

文章目录后端代码引入依赖WebSocketConfigWebSocketServiceImpl分析tb_chat_record表WebSocketServiceImplChatConfigurator聊天消息ChatTypeEnumsWebsocketMessageDTO后端 代码 引入依赖 仅需引入以下依赖 <!-- websocket依赖 --> <dependency><groupId>…

ACM8629 立体声50W/100W单声道I2S数字输入D类音频功放IC

概述 ACM8629 一款高度集成、高效率的双通道数字输入功放。供电电压范围在4.5V-26.4V,数字接口电源支持3.3V 。在4 欧负载&#xff0c;BTL模式下输出功率可以到250W1%THDN&#xff0c;在2欧负载&#xff0c;PBTL模式下单通道可以输出1100W 1%THDN. ACM8629采用新型PWM脉宽调制架…