进阶:常见API
一、Math,System
1.Math
1.1 Math概述
代表数学,是一个工具类,里面提供 的都是对数据进行操作的一些静态方法
1.2 Math常见方法
方法名 | 说明 |
---|---|
public static int abs(int a) | 获取参数绝对值 |
public static double ceil(double a) | 向上取整 |
public static double floor(double a) | 向下取整 |
public static int round(floar a) | 四舍五入 |
public static int max(int a, int b) | 获取两个int值中的较大值 |
public static double pow(double a, double b) | 返回a的b次幂的值 |
public static double random() | 返回值为double的随机值,范围[0.0,1.0] |
2.System
2.1 System概述
System代表程序所在的系统,也是一个工具类
2.2 System常见方法
方法名 | 说明 |
---|---|
public static void exit(int status) | 终止当前运行的JVM |
public static long currentTimeMills() | 返回当前系统的时间毫秒值形式 |
public static void arraycopy(源数组src,源数组要复制的起始位置srcPro,目的数组dest,目的数组的起始位置destPro,复制的长度length) | 把一个数组中某一段字节数据复制到另一个数组中 |
- 时间毫秒值:指的是从1970年1月1日 00:00:00走到此刻的总的毫秒数,应该是很大的。 1s = 1000ms
二、BigDecimal
1.BigDecimal概述
用于解决浮点型运算时,出现结果失真的问题
2.BigDecimal常见构造器、常见方法
方法 | 说明 |
---|---|
public BigDecimal(double val)不推荐使用 | 将double转换为BigDecimal |
public BigDecimal(String val) | 把String转成BigDecimal |
方法名 | 说明 |
---|---|
public static BigDecimal valueOf(double val) | 转换一个double成BigDecimal |
public BigDecimal add(BigDecimal b) | 加法 |
public BigDecimal substract(BigDecimal b) | 减法 |
public BigDecimal multiply(BigDecimal b) | 乘法 |
public BigDecimal divide(BigDecimal b) | 除法 |
public BigDecimal divide(另一个BigDecimal对象, 精确几位, 舍入模式) | 除法,可以控制精确到小数几位 |
public double doubleValue() | 将BigDecimal转换为double |
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Demo {
public static void main(String[] args) {
// BigDecimal b1 = new BigDecimal("0.5");
// BigDecimal b2 = new BigDecimal("0.3");
BigDecimal b1 = BigDecimal.valueOf(10);
BigDecimal b2 = BigDecimal.valueOf(3);
//加: add
System.out.println(b1.add(b2).doubleValue());
//减: subtract
System.out.println(b1.subtract(b2).doubleValue());
//乘: multiply
System.out.println(b1.multiply(b2).doubleValue());
//除: divide
//System.out.println(b1.divide(b2).doubleValue()); ArithmeticException算数错误
System.out.println(b1.divide(b2, 2, RoundingMode.UP).doubleValue());
}
}
三、JDK8之前的日期、时间
1.Date
1.1 Date概述
代表的是日期和时间
1.2 Data方法
构造器 | 说明 |
---|---|
public Date() | 创建一个Date对象,代表的是系统当前此刻的日期时间 |
public Date(long time) | 把时间毫秒值转换成Date日期对象 |
常见方法 | 说明 |
---|---|
public long getTime() | 返回从1970年1月1日00:00:00走到此刻的总毫秒数 |
public void setTime(long time) | 设置日期对象的时间为当前时间毫秒值对应的时间 |
package d4_bigdecimal;
import java.util.Date;
public class DemoData {
public static void main(String[] args) {
//当前系统毫秒数
Date d = new Date();
System.out.println(d);
//返回从 1970年1月1日走到此刻的毫秒数
System.out.println(d.getTime());
//输出当前时间
System.out.println(new Date(d.getTime()));
//时间的起始点 1970.01.01 (东八区,时差 8小时)
System.out.println(new Date(1));
}
}
tips:
- 日期对象如何创建,如何获取时间毫秒值
public Date(); public long getTime();
- 时间毫秒值怎么转成日期对象
public Date(long time); public void setTime(long time);
2.SimpleDataFormat
2.1 SimpleDateFormat概述
代表简单日期格式化,可以用来把日期对象、时间毫秒值格式化成我们想要的形式
2.2 SimpleDateFormat
常见构造器 | 说明 |
---|---|
public SimpleDateFormat(String pattern) | 创建简单的日期格式化对象,并封装时间的格式(yyyy-MM-dd HH:mm:ss) |
格式化时间的方式 | 说明 |
---|---|
public final String format(Date date) | 将日期格式化成 日期/时间字符串 |
public final String format(Object time) | 将时间毫秒格式化成 日期/时间字符串 |
解析方法 | 说明 |
---|---|
public Date parse(String source) | 把字符串时间解析成日期对象 |
常见日期格式:
- y 年
- M 月
- d 日
- H 时
- m 分
- s 秒
- EEE 星期几
- a 上午/下午
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateFormatDemo {
public static void main(String[] args) throws ParseException {
//定义 SimleDateFormat对象并 设置 日期的格式
SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(format1.format(new Date()));
//将一个日期用格式进行解析后输出它本来的 时间:Fri Nov 11 11:12:13 CST 2022
System.out.println(format1.parse("2022-11-11 11:12:13"));
}
}
3.Calendar
3.1 Calendar概述
代表的是系统此刻时间对应的日历,通过它可以单独获取、修改时间中的年、月、日、时、分、秒等
3.2 Calendar常见方法
方法名 | 说明 |
---|---|
public static Calendar getInstance() | 获取当前日历对象 |
public int get(int field) | 获取日历中的某个信息 |
public final Date getTime() | 获取日期对象 |
public long getTimeInMills() | 获取时间毫秒值 |
public void set(int field,int value) | 修改日历中的某个信息 |
public void add(int field,int amount) | 为某个信息增加/减少指定的值 |
import java.util.Calendar;
public class Demo1 {
public static void main(String[] args) {
//获取当前日历对象
Calendar c = Calendar.getInstance();
System.out.println(c);
//获取当前 年份
System.out.println(c.get(Calendar.YEAR));
//Calendar中的月份是从 0 开始
System.out.println(c.get(Calendar.MONTH)+1);//输出当前 月份
//输出 这天 是当月的第几天
System.out.println(c.get(Calendar.DAY_OF_MONTH));
//当前时间的 小时
System.out.println(c.get(Calendar.HOUR));
//获取 日期对象
System.out.println(c.getTime());
//获取 当前时间毫秒值
System.out.println(System.currentTimeMillis());
System.out.println(c.getTimeInMillis());
//修改当前时间的 小时 为 0
c.set(Calendar.HOUR,0);
System.out.println(c.get(Calendar.HOUR));
// 小时 减 1
c.add(Calendar.HOUR,-1);
System.out.println(c.get(Calendar.HOUR));
System.out.println(c.getTime());
}
}
四、JDK8开始新增的日期、时间
- 为什么要学JDK8新增的时间
- JDK8以前:
- 设计不合理,使用不方便,很多都被淘汰了
- 都是可变对象,修改后会丢失最开始的时间信息
- 线程不安全
- 只能精确到毫秒
- JDK8之后:
- 设计更合理,功能丰富,使用更方便
- 都是不可变对象,修改后会返回新的时间对象,不会丢失最开始的时间
- 线程安全
- 能精确到毫秒、纳秒
1.JDK8新增的时间
java.time包下的类
LocalDate: 年、月、日
LocalTime: 时、分、秒
LocalDateTime: 年、月、日、时、分、秒
ZoneId: 时区
ZonedDateTime: 带时区的时间
Instant: 时间戳/时间线
DateTimeFormatter: 用于时间的格式化和解析
Duration: 时间间隔
Peried: 时间间隔(年,月,日)
2.LocalDate,LocalTime,LocalDateTime
它们方法共同点:
方法名 | 示例 |
---|---|
public static Xxx now() | 获取系统当前时间对应的对象 LocalDate ld = LocalDate.now(); LocalTime lt = LocalTime.now(); LocalDateTime ldt = LocalDateTime.now(); |
public static Xxx of(…) | 获取指定时间的对象 LocalDate ld = LocalDate.of(2001,9,2); LocalTime lt = LocalTime.of(9.8,59); LocalDateTime ldt = LocalDateTime.of(2025,11,16,14,30,01); |
public int getXxx() | 获取指定值 int month = ld.getMonthValue(); int second = lt.getSecond(); int nano = lt.getNano(); |
withXxx | 修改某个值,返回日期对象 LocalDate ld1 = ld.withYear(2000); LocalTime lt1 = lt.withHour(10); LocalDateTime ldt1 = ldt.withNano(100000); |
plusXxx | 把某个信息加多少,返回新日期对象 LocalDate ld1 = ld.plusYears(2); LocalTime lt1 = lt.plusNanos(10000); LocalDateTime ldt1 = ldt.plusMonths(1); |
minusXxx | 把某个信息减多少,返回新日期对象 LocalDate ld1 = ld.minusYears(2); LocalTime lt1 = lt.minusNanos(10000); LocalDateTime ldt1 = ldt.minusMonths(1); |
equals、isBefore、isAfter | 判断两个日期对象,是否相等,在前还是在后 Boolean t1 = ld.equals(ld1); Boolean t2 = lt.isBefore(lt1); Boolean t3 = ldt.isAfter(ldt1); |
2.1 LocalDate
- 代表本地日期(年、月、日、星期)
2.2 LocalTime
- 代表本地时间(时、分、秒、纳秒)
2.3 LocalDateTime
- 代表本地日期、时间(年、月、日、星期、时、分、秒、纳秒)
2.4 转换相关的API
- LocalDateTime转换成LocalDate、LocalTime
方法名 说明 public LocalDate toLocalDate() 转换成一个LocalDate对象 public LocalTime toLocalTime() 转换成一个LocalTime对象
3.ZoneId、ZonedDateTime
3.1 ZoneId
代表时区Id
中国标准时间(UTC)+8小时 = 世界标准时间(UTC)
3.2 ZoneId时区的常见方法
方法 | 说明 |
---|---|
public static Set getAvaliableZoneIds() | 获取Java中支持的所有时区 |
public static ZoneId stsyemDefault() | 获取系统默认时区 |
public static ZoneId of(String zoneId) | 获取一个指定时区 |
3.3 ZonedDateTime带时区时间的常见方法
方法名 | 说明 |
---|---|
public static ZonedDateTime now() | 获取当前时区的ZonedDateTime对象 |
public static ZonedDateTime now(ZoneId zone) | 获取指定时区的ZonedDateTime对象 |
getXxx(Year,MonthValue,DayOfMonth,Hour,Nano) | 获取年、月、日、时、分、秒等 |
public ZonedDateTime withXxx(时间) | 修改时间系列的方法 |
public ZonedDateTime plusXxx(时间) | 增加时间系列的方法 |
public ZonedDateTime minusXxx(时间) | 减少时间系列的方法 |
4.Instant
- 通过获取Instant的对象可以拿到此刻的时间,该时间由两部分组成:从1970-01-01 00:00:00 开始走到此刻的总秒数 + 不够1秒的纳秒数
4.1 Instant常见方法
方法名 | 说明 |
---|---|
public static Instant now() | 获取当前时间的Instant对象(标准时间) |
public long getEpochSecond() | 获取从1970-01-01T00:00:00开始记录的秒数 |
public int getNano() | 从时间线开始,获取从第二个开始的纳秒数 |
plusXxx(Seconds,Millis,Nanos) | 增加时间系列的方法 |
minusXxx(Seconds,Millis,Nanos) | 减少时间系列的方法 |
equals、isBefore、isAfter | 判断系列的方法 |
4.2 Instant作用
- 可以用来记录代码的执行时间,或用于记录用户操作某个事件的时间点
- 传统的Date类,只能精确到毫秒,并且是可变对象;
- 新增的Instant类,可以精确到纳秒,并且是不可变对象,推荐用Instant代替Date
5.DateTimeFormatter
方法名 | 说明 |
---|---|
public static DateTimeFormatter ofPattern(时间格式) | 获取格式化对象 |
public String format(时间对象) | 格式化时间 |
- LocalDateTime提供的格式化、解析时间的方法
方法名 | 说明 |
---|---|
public String format(DateTimeFormatter formatter) | 格式化时间 |
public static LocalDateTime parse(CharSequence text, DateTimeFormatter formatter) | 解析时间 |
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
public class DFormatter {
public static void main(String[] args) {
//创建一个 DateTimeFormatter 格式化对象
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
//方式一:dtf.format(now)-- DateTimeFormatter提供的format(日期对象)方法
String now1 = dtf.format(now);
System.out.println(now1);
//方式二:now1.format(dtf)-- LocalDateTime提供的format(格式化对象)方法
String s1 = now.format(dtf);
System.out.println(s1);
//解析
String dateStr = "2023-12-19 09:15:51";
//TemporalAccessor parse = dtf.parse(dateStr); 一般不推荐使用
//LocalDateTime parse = (LocalDateTime) dtf.parse(dateStr);//报错:ClassCastException类型转换异常【不推荐】
LocalDateTime s = LocalDateTime.parse(dateStr, dtf);
System.out.println(s);
}
}
6.Perioed(一段时期)
- 可以用于计算两个LocalDate对象相差的 年、月、天数
方法名 | 说明 |
---|---|
public static Period between(LocalDate start, LocalDate end) | 传入2个日期对象,得到Period对象 |
public int getYears() | 计算隔几年,并返回 |
public int getMonths() | 计算隔几个月,年返回 |
public int getDays() | 计算隔多少天,并返回 |
import java.time.LocalDate;
import java.time.Period;
public class PriodDemo {
public static void main(String[] args) {
LocalDate startDate = LocalDate.of(2023, 12, 12);
LocalDate endDate = LocalDate.of(2021, 11, 11);
Period period = Period.between(startDate, endDate);
//相差的 年
int years = period.getYears();
System.out.println(years);
//获取 相差的 月份
System.out.println(period.getMonths());
//获取 相差的天数
System.out.println(period.getDays());
}
}
7.Duration(持续时间)
- 可以用于计算两个时间对象相差的天数、小时数、分数、秒数、纳秒数;支持LocalTime、LocalDateTime、Instant等时间
方法名 | 说明 |
---|---|
public static Duration between(开始时间对象1,截止时间对象2) | |
import java.time.Duration;
import java.time.LocalTime;
public class DurationDemo {
public static void main(String[] args) {
LocalTime startTime = LocalTime.of(10, 10, 10);
LocalTime endTime = LocalTime.of(12, 12, 12);
//Duration.between(start,end) 传入两个日期对象,得到Duration对象
Duration du = Duration.between(startTime, endTime);
//间隔 小时
System.out.println(du.toHours());
//间隔 分钟
System.out.println(du.toMinutes());
//间隔 毫秒
System.out.println(du.toMillis());
}
}
五、Arrays
- 用来操作数组的一个工具类
1.Arrays类提供的常见方法
方法名 | 说明 |
---|---|
public static String toString(类型[] arr) | 返回数组的内容 |
public static int[] copyOfRange(类型[] arr, 起始索引, 结束索引) | 拷贝数组(指定范围)包左不包右 |
public static void sort(类型[] arr) | 对数组进行排序(默认:升序) |
import java.util.Arrays;
public class ArraysDemo {
public static void main(String[] args) {
// toStirng() 返回数组的内容【一般测试使用】
int[] arr = {11, 55, 33, 44};
String s = Arrays.toString(arr);
System.out.println(s);
//copyOfRange(数组, startIndex, endIndex) 拷贝数组
//-- [startIndex, endIndex) 包左不包右
int[] arr2 = Arrays.copyOfRange(arr, 1, 3);
System.out.println(Arrays.toString(arr2));
//对数组进行排序 sort()
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
六、JDK8新特性
1.Lambda表达式
1.1 Lambda表达式概述
- Lambda表达式是JDK 8开始新增的一种语法形式
作用:用于简化匿名内部类的代码写法
函数式接口
- 有且仅有一个抽象方法的接口
- 注意:将来我们见到的大部分函数式接口,上面都可能会有一个==@FunctionalInterface==的注解,有该注解的接口就必定是函数式接口
1.2Lambda表达式的省略规则
- 参数类型无条件省略
- 如果只有一个参数,参数类型可以省略,同时()也可以省略
- 如果Lambda表达式中的方法体代码只有一行代码,可以省略大括号不写,同时要省略分号!此时,如果这行代码是return语句,也必须去掉return不写
import java.util.Arrays;
import java.util.Comparator;
public class StuCompareDemo {
public static void main(String[] args) {
Student[] students = new Student[4];
students[0] = new Student("蜘蛛精",169.5,23);
students[1] = new Student("紫霞",163.5,26);
students[2] = new Student("紫霞",163.5,26);
students[3] = new Student("至尊宝",167.5,24);
/*
* 自然排序:
* 1.对象实体类中 implements Compareble<对象类名>
2.对象实体类中 重写 Comparabel接口的 CompareTo方法
3.升序> this.属性值 - 形参.属性值
* 降序> 形参.属性值 - this.属性值
*/
// Arrays.sort(students);
// System.out.println(Arrays.toString(students));
//比较器排序:
/*Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return (int) (o1.getHeight()-o2.getHeight());
}
});
*/
// Arrays.sort(students,(Student o1,Student o2) -> {
// return (int)(o1.getHeight() - o2.getHeight());
// });
//Lambda省略规则简化后的代码
/*
省略规则:
1.参数类型无条件省略
2.如果只有一个参数,参数类型可以省略,同时()也可以省略
3.如果Lambda表达式中的方法体代码只有一行代码,可以省略大括号不写,同时要省略分号!
此时,如果这行代码是return语句,也必须去掉return不写
*/
//Arrays.sort(students,(o1, o2) -> (int)(o1.getHeight() - o2.getHeight()));
//静态方法优化
//Arrays.sort(students,StuSort::sortStudent);
//实例方法优化
StuSort sort = new StuSort();
// Arrays.sort(students,sort.sortStudent(o1,o2));
System.out.println(Arrays.toString(students));
}
}
2.方法引用
2.1 静态方法的引用
类名::静态方法
使用场景:如果某个Lambda表达式里只是调用一个静态方法,并且前后参数的形式一致,就可以使用静态方法引用
2.2 实例方法的引用
- 对象名::实例方法
- 使用场景:如果某个Lambda表达式里只是调用一个实例方法,并且前后参数的形式一致,就可以使用实例方法引用
2.3 特定类型的方法引用
- 类型::方法
- 使用场景:如果某个Lambda表达式里只是调用一个实例方法,并且前面参数列表中的第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用
2.4 构造器引用
- 类名::new
- 使用场景:如果某个Lambda表达式里只是在创建对象,并且前后参数情况一致,就可以使用构造器引用
2.5 使用案例
- 自然排序
public class Student implements Comparable<Student>{
private String name;
private int age;
private int chinese;
private int english;
//语文成绩升序排列
@Override
public int compareTo(Student o) {
if (this.chinese == o.chinese){
return this.english - o.english;
}else{
return this.chinese - o.chinese;
}
}
//重写的 toString()
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", chinese=" + chinese +
", english=" + english +
'}';
}
get,set,构造器();
}
//main 方法
import java.util.Arrays;
import java.util.Comparator;
public class StuDemo {
public static void main(String[] args) {
Student[] stus = new Student[6];
stus[0] = new Student("zhangsan", 17, 99, 77);
stus[1] = new Student("lisi", 21, 85, 86);
stus[2] = new Student("wangwu", 20, 75, 94);
stus[3] = new Student("zhaoliu", 17, 75, 95);
stus[4] = new Student("qianqi", 19, 66, 44);
stus[5] = new Student("yanzu", 18, 75, 86);
//自然排序
Arrays.sort(stus);
System.out.println(Arrays.toString(stus));
}
}
- 比较器排序
public class Student{
private String name;
private int age;
private int chinese;
private int english;
//重写的 toString()
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", chinese=" + chinese +
", english=" + english +
'}';
}
get,set,构造器();
}
//main 方法
import java.util.Arrays;
import java.util.Comparator;
public class StuDemo {
public static void main(String[] args) {
Student[] stus = new Student[6];
stus[0] = new Student("zhangsan", 17, 99, 77);
stus[1] = new Student("lisi", 21, 85, 86);
stus[2] = new Student("wangwu", 20, 75, 94);
stus[3] = new Student("zhaoliu", 17, 75, 95);
stus[4] = new Student("qianqi", 19, 66, 44);
stus[5] = new Student("yanzu", 18, 75, 86);
//比较器排序
Arrays.sort(stus, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return ageNameReg(o1,o2);
}
});
//前面代码 Lambda 优化后:
Arrays.sort(stus,((o1, o2) -> o1.getAge()-o2.getAge()));
//再次优化,使用【静态方法】优化后:
Arrays.sort(stus, StuDemo::ageNameReg);
System.out.println(Arrays.toString(stus));
}
public static int ageNameReg(Student o1,Student o2){
if (o1.getAge() == o2.getAge()){
if (o1.getName().charAt(0) == o2.getName().charAt(0)){
return o1.getName().length() - o2.getName().length();
}else {
return o1.getName().charAt(0) - o2.getName().charAt(0);
}
}else {
return o1.getAge() - o2.getAge();
}
}
}