十一、常用API
11.1 math
math类介绍
- 是一个帮助我们进行数学计算的工具类
- 私有化构造方法,所有的方法都是静态的
math类的常用方法
- public static int abs(int a) 获取参数绝对值
- public static double ceil(double a) 向上取整
- public static double floor(double a) 向下取整
- public static int round(float a) 四舍五入
- public static int max(int a, int b) 获取两个int值的较大值
- public static double pow(double a, double b) 返回a的b次幂
- public static double random() [0.0,1.0)随机数
11.2 System
System类介绍
System类也是一个工具类,提供了一些与系统相关的方法。
System类的常用方法
-
public static void exit(int status) 中止当前的java虚拟机
状态码
- 0:表示当前虚拟机是正常停止。当需要把整个程序都结束的时候就调用这个方法。
- 非0:表示虚拟机是异常停止。
-
public static long currentTimeMillis() 返回当前系统的时间毫秒形式
- 计算机中的事件原点:1970年1月1日 00:00:00 ,c语言的生日。
- 由于时区的存在,我国的原点时间是1970年1月1日 08:00:00
-
public static void arraycopy(数据源数组,起始索引,目的地数组,起始索引,拷贝个数) 数组拷贝
- 如果数据源数组和目的地数组都是基本数据类型,那么两者的类型必须保持一致,否则会报错。
- 在拷贝的时候需要考虑数组的长度,如果超出范围会报错。
- 如果数据源数组和目的地数组都是引用数据类型,那么子类类型可以赋值给父类类型。
11.3 Runtime
Runtime介绍
Runtime表示当前虚拟机的运行环境。
Runtime类的常用方法
- public static Runtime getRuntime() 当前系统的运行环境对象
- public void exit(int status) 停止虚拟机(System的exit方法底层实现就是调用Runtime的exit方法)
- public int availableProcessors() 获取CPU线程数
- public long maxMemory() JVM能从系统中获取的内存大小(单位byte)
- public long totalMemory JVM已经从系统中获取的内存大小(单位byte)
- public long freeMemory() JVM剩余内存大小(单位byte)
- public Process exec(String command) 运行CMD命令
11.4 Object和Objects
Object介绍
- Object是java中的顶级父类,所有的类都直接或间接继承于object类。
- Object类中的方法可以被所有子类访问,所以需要学习Object类和其中的方法。
Object的构造方法
- public Object() 空参构造
Object的成员方法
-
public String toString() 返回对象的字符串表示形式
再看System.out.println()
- System是类名
- System.out获取打印的对象
- println是方法,核心逻辑是调用对象的toString方法把对象变成字符串打印在控制台上,打印完毕换行处理。
-
public boolean equals(Object obj) 比较两个对象是否相等
- 如果没有重写equals方法,那么默认使用Object中的方法进行比较,比较的是地址值是否相等。
- 一般来讲地址值意义不大,所以需要在子类中重写。
String s = "abc";
StringBuilder sb = new StringBuilder("abc");
System.out.println(s.equals(sb));//false
System.out.println(sb.equals(s));//false
/*
第一个为false原因:
String中的equals方法经过重写,重写后的逻辑为先判断是否为字符串,若是字符串才比较内部属性。如果参数不是字符串,直接返回false。
第二个为false原因:
StringBuilder没有重写equals方法,使用的是Object类中的equal方法。默认比较的是两个对象的地址值。
*/
-
protected Object clone(int a) 对象克隆
-
把A对象的属性值完全拷贝给B对象,也叫对象拷贝,对象复制。
-
方法在底层会帮我们创建一个对象,并把原对象的数据拷贝过去。
克隆步骤:
- 1.重写Object中的clone方法。
- 2.让javabean类实现Cloneable接口。
- 3.创建原对象并调用clone。
-
浅克隆和深克隆
- 浅克隆:不管对象内部的属性是基本数据类型还是引用数据类型,都全部拷贝过来。(Object克隆是浅克隆)
- 深克隆:基本数据类型直接拷贝,字符串复用,引用数据类型直接创建新的。
-
Objects类介绍
Objects是一个工具类,提供了一些方法去完成一些功能。
Objects的成员方法
- public static boolean equals(object a,object b) 先做非空判断,比较两个对象
- 方法底层判断a是否为null,如果为null,直接返回false
- a不为null,那么利用a再次调用equals方法
- 如果a是子类,那么会调用子类中的equals方法,没有重写,比较地址值,重写了则比较属性值。
- public static boolean isNull(Object obj) 判断对象是否为null,为null则返回true
- public static boolean nonNull 判断对象是否为null,和isNull结果相反
11.5 BigInteger 和 BigDecimal
BigInteger
在java中,整数有四种类型:byte,short,int,long
在底层占用字节个数:byte1个字节,short2个字节,int4个字节,long8个字节
BigInteger构造方法
- public BigInteger(int num, Random rnd) 获取随机大整数 范围[0,2^num - 1]
- public BigInteger(String val) 获取指定的大整数,字符串必须是整数,否则报错
- public BigInteger(String val, int radix) 获取指定进制的大整数
- public static BigInteger valueOf(long val) 静态方法获取BigInteger的对象,内部有优化
- 提前把-16~16先创建好BigInteger的对象,如果多次获取不会创建新的
BigInteger对象一旦创建,内部记录的值不能发生改变。
构造方法小结
- 如果BigInteger表示的数字没有超过long的范围,可以用静态方法获取。
- 如果BigInteger表示超过long的范围,可以使用构造方法获取。
- 对象一旦创建,BigInteger内部记录的值不能发生改变。
- 只要进行计算都会产生一个新的BigInteger对象。
BigInteger常见成员方法
- public BigInteger add(BigInteger val) 加法
- public BigInteger substract(BigInteger val) 减法
- public BigInteger multiply(BigInteger val) 乘法
- public BigInteger divide(BigInteger val) 除法,获取商
- public BigInteger[] divideAndRemainder(BigInteger val) 除法,获取商和余数
- public Boolean equals(Object x) 比较是否相同
- public BigInteger pow(int exponent) 次幂
- public BigInteger max/min(BigInteger val) 返回较大值,较小值
- 不会创建新的对象,返回符合要求的对象
- public int intValue(BigInteger val) 转为int类型整数,超出范围数据有误
BigInteger底层存储方式
- 对于计算机而,没有数据类型这个概念,都是0和1。
- 数据类型是编程语言自己规定的。
- 包含signum和mag两个属性,将大数字拆开存储。
BigDecimal介绍
- 用于小数的精确计算
- 用来表示很大的小数
BigDecimal构造方法
- public BigDecimal(double val)不精确,不建议使用
- public BigDecimal(string val)
- public static BigDecimal valueOf(double val) 静态方法
注意事项
- 如果表示的数字不大,没有超出double的表示范围,建议使用静态方法。
- 如果表示的数字比较大,超出了double的表示范围,建议使用构造方法。
- 如果传递的是0-10之间的整数,那么方法会返回已经创建好的对象,不会重新new。
Bigdecimal的方法
- public Bigdecimal add(BigDecimal val) 加法
- public Bigdecimal substract(BigDecimal val) 减法
- public Bigdecimal multiply(BigDecimal val) 乘法
- public Bigdecimal divide(BigDecimal val) 除法,除不尽会报错
- public Bigdecimal divide(BigDecimal val, 精确几位, 舍入模式) 除法
BigDecimal底层存储方式
拆成字符,存储字符对应的ascii码数值。
11.6 正则表达式
正则表达式作用
- 正则表达式可以校验字符串是否满足一定的规则,用来检验数据格式的合法性。
- 在一段文本中查找满足要求的内容。
正则表达式
字符类:
[]表示一个范围
[abc] 只能是a,b或c
[^abc]除了abc之外的任何字符
[a-zA-Z]a到z或者A到Z
[a-d[m-p]]a到d或者m到p,和上面一样
[a-z&&[def]]a到z和def的交集。为d,e,f 如果只写了一个&,那么单单表示一个&符号而已
[a-z&&[ ^bc ] ]a-z和非bc的交集。等同于[ad-z]
[a-z&&[ ^m-p]]a到z和除了m到p的交集。等同于[a-lq-z]
预定义字符:
. 任意字符
\d 一个数字[0-9]
\D 非数字[ ^ 0 - 9]
\s 一个空白字符[\t \b \x0B \f \r ]
\S 非空白字符[ ^ \s]
\w [a-zA-Z_0-9]英文字母下划线
\W[ ^\w] 一个非单词字符
数量词
X? X,一次或0次
X*,X,零次或者多次
X+,X,一次或者多次
X{n} X,正好n次
X{n,} X,至少n次
X{n,m} X,至少n但不超过m次
正则表达式爬虫
regex下的两个类
- Pattern:表示正则表达式
- Matcher:文本匹配器,作用按照正则表达式的规则去读取字符串,从头开始读取。在大串中去找符合规则的子串。
import java.util.regex.Pattern;
import java.util.regex.Matcher;
//1.获取正则表达式的对象
Pattern p = pattern.compile("正则表达式");
//m 文本适配器的对象
//p规则
//m要在str中寻找符合p规则的小串
//2.获取文本匹配器的对象
Matcher m = p.matcher(str);
//3.利用循环获取
while(m.find()) {
string s = m.group();
System.out.println(s);
}
/*详细过程说明
//拿着文本适配器从头开始读取,寻找是否有满足规则的子串
//如果没有返回false
//有则返回true,在底层记录起始索引和结束索引+1
boolean b = m.find();
//方法会根据find方法记录的索引进行字符串的截取
//substring
String s1 = m.group();
System.out.println(s1);
//第二次调用find的时候,会继续读取后面的内容
b = m.find();
String s2 = m.group();
System.out.println(s2);
*/
网络爬虫举例
public class RegexDemo {
public static void main(String[] args) {
//创建url对象
URL url = new URL("url");
//连接网址
URLConnection conn = url.openConnection();
//创建一个对象读取网络中的数据
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
//获取正则表达式对象pattern
String regex = "[1-9]\\d{17}";
Pattern pattern = Pattern.compile(regex);
while((line = br.readLine()) != null) {
Matcher matcher = pattern.matcher(line);
while(matcher.find()) {
System.out.println(matcher.group());
}
}
br.close();
}
}
带条件爬取
//需求1:爬取版本号为8,11,17的java版本,但是只要java,不显示版本号。
//?理解为前面的数据java,=表示java后面跟随的数据,但在获取的时候,只获取前半部分。
String regex = "java(?=8|11|17)";
//需求2:爬取版本号为8,11,17的java版本,正确爬取结果为:java8 java11 java 17
String regex = "java(?:8|11|17)";
String regex = "java(8|11|17)";
//需求2:爬取除了版本号为8,11,17的java版本
String regex = "java(?!8|11|17)";
贪婪爬取和非贪婪爬取
贪婪爬取:在爬取数据的时候尽可能的多获取数据。
非贪婪爬取:在爬取数据的时候尽可能的少获取数据。
java中,默认就是贪婪爬取。如果在数量词+ *后面加上问号,那么此时就是非贪婪爬取。
String = "abbbbbbbbbbbabaaaaaaaaaaaaaaaaaaaaaaaaaaa";
//需求1:按照ab+的方式爬取ab,b尽可能多获取
String regex = "ab+";
//需求2:按照ab+的方式爬取ab,b尽可能少获取
String regex = "ab+?";
正则表达式在字符串方法中的使用
- public String[] matches(String regex) 判断字符串是否满足正则表达式的规则
- public String replaceAll(String regex, String newStr) 按照正则表达式的规则进行替换
- public String[] split(String regex) 按照正则表达式的规则切割字符串
String s = "字符串";
//需求1:替换字符串
//底层实现:Pattern.compile(regex).matcher(this).replaceAll(replacement)
String result = s.replaceAll(regex,replacement);
//需求2:把字符串中的三个姓名切割出来
String[] result = s.split(regex);
正则表达式的分组规则
- 规则1:从1开始,连续不间断。
- 规则2:以左括号为基准,最左边的是第一组,其次为第二组,以此类推。
捕获分组
捕获分组就是把这一组的数据捕获出来,再用一次。
正则表达式内部使用:\ \组号
正则表达式外部使用:$
//需求1:判断一个字符串的开始字符和结束字符是否一致?只考虑一个字符。
//举例:a123a b456b 17981 &abc&
// \\组号,表示把第x组的内容再出来用一次
String regex1 = "(.).+\\1";
//需求2:判断一个字符串的开始部分和结束部分是否一致?可以多个字符。
//举例:abc123abc 123789123
String regex2 = "(.+).+\\1";
//需求3:判断一个字符串的开始部分和结束部分是否一致?开始部分内部每个字符也要一致。
//举例:aaa123aaa bbb456bbb 111789111
//(,)\\2* 保证开始部分一致
String regex2 = "((.)\\2*).+\\1"
非捕获分组
分组之后不需要再用本组数据,仅仅是把数据括起来。这种用法不占用组号。
(? : )(?!)(?=)都是非捕获分组。
11.6 时间相关类
JDK前时间相关类
- Date 时间
- SimpleDateFormat 格式化时间
- Calendar 日历
Date时间类
Date类是一个JDK写好的JavaBean类,用来描述时间,精确到毫秒。
利用空参构造创建的对象,默认表示系统当前时间。
利用有参构造创建的对象,表示指定的时间。
//1.创建一个对象表示时间
Date d1 = new Date();
System.out,println(d1);
//2.创建一个对象表示指定的时间
Date d2 = new Date(0L);//表示从时间原点开始,过了0毫秒的时间。
System.out.println(d2);
//3.setTime修改时间
d2.setTime(1000L);//表示从时间原点开始,过了1000毫秒时间
System.out.println(d2);
//4.getTime获取当前时间毫秒值
long time = d2.getTime();//1000
System.out.println(time);
SimpleDateFormat类
作用:
- 格式化:把时间变成易于阅读的形式。
- 解析:把字符串表示的时间变成Date对象。
构造方法:
- public SimpleDateFormat() 构造一个SimpleDateFormat,使用默认格式。
- public SimpleDateFormat(String pattern) 构造一个SimpleDateFormat,使用指定格式。
常用方法:
- public final String format(Date date) 格式化(日期对象 -> 字符串)
- public Date parse(String source) 解析(字符串->日期对象)
//1.利用空参构造创建SimpleDateFormat对象,默认格式
SimpleDateFormate sdf1 = new SimpleDateFormat();
Date d = new Data(0L);
String str1 = sdf1.format(d);
//1.利用带参构造创建SimpleDateFormat对象,指定格式
SimpleDateFormate sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String str2 = sdf2.format(d);
//1.定义一个字符串表示时间
String str = "2023-11-11 11:11:11";
//2.利用空参构造创建SimpleDateFormat对象
//创建对象的格式要和字符串的格式完全一致
SimpleDateFormate sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse(str);//ctrl + alt + v自动生成左边
//3.打印结果
System.out.println(date);
Calendar类
- Calendar代表了系统当前时间的日历对象,可以单独修改、获取时间中的年,月,日。
- Calendar是一个抽象类,不能直接创建对象。
获取Calendar日历类对象的方法
public static Calendar getInstance() 获取当前时间的日历对象
Calendar常用方法
- public final Date getTime() 获取日期对象
- public final 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) 为某个字段增加、减少指定的值
//1.获取日历对象
//Calendar是一个抽象类,不能直接new,而是通过一个静态方法获取子类对象
//底层原理:根据系统的不同时区来获取不同的日历对象。会把事件中的纪元、年月日等等放入一个数组当中。
Calendar c = Calendar.getInstance();
//2.修改日历代表的时间
//月份范围是0-11.星期日是一周中的第一天
Date d = new Date(0L);
c.setTime(d);
//0:纪元 1:年 2:月 3:一年中的第几周 4:一个月中的第几周 5:一个月中的第几天
//java在calendar类中,把索引对应的数字都定义成常量
int year = c.get(1);
int year = c.get(Calendar.YEAR);
JDK8新增时间类
原因
JDK8时间类
Zoneid时区常用方法
- static Set getAvailableZoneIds() 获取java中支持的所有时区
- static ZoneId systemDefault() 获取系统默认时区
- static ZoneId of(String ZoneId) 获取一个指定时区
//1.获取所有的时区名称
Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
//2.获取当前系统的默认时区
ZoneId ZoneId = ZoneId.systemDefault();
//3.获取指定的时区
ZoneId ZoneId1 = ZoneId.of("Asia/Shanghai");
Instant时间戳
- static Instant now() 获取当前的Instant时间(标准时间)
- static Instant ofxxx(long epochMilli) 根据(秒/毫秒/纳秒)获取Instant对象
- ZonedDateTime atZone(ZoneId zone) 指定时区
- boolean isXXX(Instant otherInstant) 判断系列的方法
- Instant minusXxx(long millisToSubstract) 减少时间系列的方法
- Instant plusXxx(long millisToSubtract) 增加时间系列的方法
//1.获取当前时间的Instant对象
Instant now = Instant.now();
//2.根据(秒/毫秒/纳秒)获取Instant对象
Instant instant1 = Instant.ofEpochMilli(0L);
Instant instant2 = Instant.ofEpochSecond(1L);
Instant instant3 = Instant.ofEpochSecond(1L,1000000000L);//第一个参数单位秒,第二个参数为纳秒
//3.指定时区
ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
//4.isXxx 判断
//isBefore:判断调用者代表的时间是否在参数表示时间的前面
Instant instant4 = Instant.ofEpochMilli(0L);
Instant instant5 = Instant.ofEpochMilli(1000L);
boolean isBefore = Instant4.isBefore(instant5);
//5.减少时间系列的方法
Instant instant6 = Instant.ofEpochMilli(10000L);
Instant instant7 = Instant6.minusSecond(1);
ZonedDateTime带时区的时间
- static ZonedDateTime now() 获取当前时间的ZoneDateTime对象
- static ZonedDateTime ofXxx() 获取指定时间的ZonedDateTime对象
- ZonedDateTime withXxx(时间) 修改时间系列的方法
- ZonedDateTime minusXxx(时间) 减小时间系列的方法
- ZonedDateTime plusXxx(时间) 增加时间系列的方法
//1.获取当前时间对象(带时区)
ZonedDateTime now = ZonedDateTime.now();
//2.获取指定的时间对象
ZonedDateTime time1 = ZonedDateTime.of(2023,10,1,11,12,12,0,ZoneId.of("Asia/Shanghai"));
//通过Instant+时区的方式指定获取时间对象
Instant instant = Instant.ofEpochMilli(0L);
ZoneId zoneId = ZoneId.of("Asia/Shanghai");
ZonedDateTime time2 = ZonedDateTime.ofInstant(instant,ZoneId);
//3.withXxx修改时间系列的方法
ZonedDateTime time3 = time2.withYear(2000);//修改年份为2000
//4.减少时间
ZonedDateTime time4 = time2.minusYear(1);
//5.增加时间
ZonedDateTime time5 = time2.plusYear(1);
//JDK8新增的时间对象是不可变的,如果修改时间,调用者是不会发生改变而是产生一个新的时间。
DateTimeFormatter时间格式化类
- static DateTimeFormatter ofPattern(格式) 获取格式对象
- String format(时间对象) 按照指定方式格式化
//获取时间对象
ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
//解析/格式化器
DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH;mm;ss EE a");
//格式化
System.out.println(dft1.format(time));
日历类LocalDate、LocalTime、LocalDateTime
- static XXX now() 获取当前时间的对象
- static XXX of(…) 获取指定的时间对象
- get开头的方法 获取日历中的年月日时分秒等信息
- isBefore、isAfter 比较两个LocalTime
- with开头的方法 修改时间系列的方法
- minus开头的方法 减少时间系列的方法
- plus开头的方法 增加时间系列的方法
- LocalDateTime转LocalDate、LocalTime
- public LocalDate toLocateDate()
- public LocalTime toLocateTime()
//1.获取当前的日历对象
LocalDate nowDate = LocalDate.now();
//2.获取指定的时间的日历对象
LocalDate idDate = LocalDate.of(2023,1,1);
//3,get系列方法获取日历中的每一个属性值
int year = idDate.getYear();
//is开头表示判断
idDate.isBefore(idDate);
//with开头表示修改 minus表示减少 plus表示增加
LocalDate dateTime = idDate.withYear(2000);
LocalDate dateTime = idDate.plusYear(1);
LocalDate dateTime = idDate.minusYear(1);
工具类Duration、Period、ChronoUnit
- Duration 计算两个时间的时间间隔
- Period 计算两个日期的时间间隔
- ChronoUnit 计算两个日期的间隔
Period period = Period.between(birthDate,today);//第二个参数减第一个参数
Duration duration = Duration.between(birthDate,today);
ChronoUnit.YEARS.between(birthDate,today);//相差多少年
11.7 包装类
什么是包装类
包装类:基本数据类型对应的引用数据类型。
获取Integer对象的方式
两种方式获取对象的区别:
new关键字每一次new都创建一个新的对象,所以地址值不同。
valueof底层将-128-127创建好数组,127之内的返回已经创建好的数组。
//以前的包装类如何进行计算
//1.把对象进行拆箱,变成基本数据类型。
//2.计算
int result = i1.intValue() + i2.intValue;
//3.把得到的结果再次进行装箱
Integer i3 = new Integer(result);
//JDK5提出自动装箱和自动拆箱机制
//自动装箱:把基本数据类型自动变成其对应的包装类
//自动拆箱:把包装类自动变成其对象的基本数据类型
Integer i = 10;//在底层,还会调用静态方法valueOf得到一个Inter对象。自动装箱
//自动拆箱
Integer i2 = new Integer(10);
int i = i2;
//JDK5之后,int和Integer可以看作同一个东西,因为内部可以自动转化。
Integer成员方法
- public static String toBinaryString(int i) 得到二进制
- public static String toOctalString(int i) 得到八进制
- public static String toHexString(int i 得到十六进制
- public static int parselent(String s) 将字符串类型的整数转成int类型的整数
//把整数变成二进制
String str1 = Integer.toBinaryString(100);
//将字符串类型的整数转成int类型的整数
int i = Integer.parseInt("123");
//在类型转换的时候,括号里面只能是数字不能是其他,否则代码会报错。
//8中包装类中,除了Charcter都有对应的parseXXX方法进行类型转换。