# 常用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));//-2147483648System.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返回值类型为doublepow的第二个参数建议为大于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
}
}
注意
- 如果数据源数组和目的地数组都是基础数据类型,那么两者的类型必须保持一致,否则会报错
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);
}
}
- 在拷贝的时候需要考虑数组的长度,如果超出范围就会报错
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);
}
}
- 如果数据源数组和目的地数组都是引用类型,那么子类类型可以赋值给父类类型
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是所有类的父类,所有类都直接或间接继承自ObjecttoString一般会重写,打印对象时打印属性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;
}
}
# isNull与nonNull
isNull与nonNull都是Objects中的静态方法,用于判断对象是否为null,nonNull的结果与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
# 思路:把正确的数据分为三部分
- 第一部分:@的左边任意字符至少出现一次
- 第二部分:@ 一定出现一次 @
- 第三部分:@的右边
- .的左边
[\\w&&[^_]]{2,6}任意的字母加数字(且不能出现下划线) \\.一定出现. 且只出现一次- 大写字母。小写字母都可以只能出现2-3次
[a-zA-Z]{2,3} (\\.[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
- @ 一定出现一次 @
- @的右边
- 在.左边
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方法的效果,将字符串形式的数据转换成整数
要求
- 字符串中只能是数字不能有其他字符
- 至少一位,至多10位
- 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();
}
}