StringJoiner类

在使用String类型来对字符串进行拼接的时候,往往效率是很慢的。所以我们才会改用StringBuilderStringBuffer来进行操作。但是代码会变得繁琐。

但是在JDK8开始推出了StringJoiner,跟StringBuilder一样,也是用来操作字符串的,也可以看成是一个容器,创建之后里面的内容是可变的。

好处:不仅能提高字符串的操作效率,并且在有些场景下使用它操作字符串,代码会更简洁。

示例:

1
2
3
4
5
6
7
//可以指定拼接字符串时用的间隔符
public StringJoiner(间隔符号, 开始符号, 结束符号)
StringJoiner s = new StringJoiner(",", "[", "]");
s.add("java1");
s.add("java2");
s.add("java3");
//输出:[java1,java2,java3]

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() 返回值为double的随机值,范围[0.0, 1.0)

System类

System代表程序所在的系统,也是一个工具类

常用方法:

public static long currentTimeMillis(),该方法为获取到目前系统的时间,返回的是时间戳。

BigDecimal类

在Java中,我们计算浮点型数据可能会导致计算精度缺失。所以Java给我们提供了BigDecimal类,它提供了一些方法可以对数据进行四则运算,而且不丢失精度,同时还可以保留指定的小数位。

使用注意:

  • public BigDecimal(double val) 得到的BigDecimal对象是无法精确计算浮点型数据的。
    • 【注意】在阿里巴巴的Java开发手册中提到:禁止使用构造方法public BigDecimal(double val)把double值转换成BigDecimal对象。
  • public BigDecimal(String val) 得到的BigDecimal对象是可以精确计算浮点型数据的。 可以使用。
  • public static BigDecimal valueOf(double val)通过这个静态方法得到的BigDecimal对象是可以精确运算的。是最好的方案。
  • 在计算诸如0.1 / 0.3这样无法除净的除法运算时候,由于使用BigDecimal c4 = a1.divide(b1);会报错,所以推荐使用public BigDecimal divide(另一个BigDecimal对象,精确几位,舍入模式)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
double a = 0.1;
double b = 0.2;

BigDecimal a1 = BigDecimal.valueOf(a);
BigDecimal b1 = BigDecimal.valueOf(b);

// 2、public BigDecimal add(BigDecimal augend): 加法
BigDecimal c1 = a1.add(b1);

// 3、public BigDecimal subtract(BigDecimal augend): 减法
BigDecimal c2 = a1.subtract(b1);

// 4、public BigDecimal multiply(BigDecimal augend): 乘法
BigDecimal c3 = a1.multiply(b1);

// 5、public BigDecimal divide(BigDecimal b): 除法
BigDecimal c4 = a1.divide(b1);

// 6、public BigDecimal divide(另一个BigDecimal对象,精确几位,舍入模式) : 除法,可以设置精确几位。
BigDecimal d1 = BigDecimal.valueOf(0.1);
BigDecimal d2 = BigDecimal.valueOf(0.3);
BigDecimal d3 = d1.divide(d2, 2, RoundingMode.HALF_UP); // 0.33

Date类

代表的是日期和时间

常见方法

常见方法 说明
public long getTime() 返回从1970年1月1日 00:00:00走到此刻的总毫秒数(时间戳)
public void setTime(long time) 设置日期对象的时间为当前时间毫秒值对应的时间

SimpleDateFormat类

代表简单日期格式化,可以用来把日期对象、时间毫秒值格式化成我们想要的格式

格式化时间的方法 说明
public final String format(Date date) 将日期格式化成日期/时间字符串
public final String format(Object time) 将时间毫秒值式化成日期/时间字符串

格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
字母	   表示含义
yyyy 年
MM 月
dd 日
HH 时
mm 分
ss 秒
SSS 毫秒

"2022年12月12日" 的格式是 "yyyy年MM月dd日"
"2022-12-12 12:12:12" 的格式是 "yyyy-MM-dd HH:mm:ss"
//按照上面的格式可以任意拼接,但是字母不能写错

// 2、格式化日期对象,和时间 毫秒值。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a");

SimpleDateFormat解析字符串时间成为日期对象

解析方法 说明
public Date parse(String source) 把字符串时间解析成日期对象

示例:

1
2
3
4
5
6
7
public static void main(String[] args) throws ParseException {
String dateStr = "2022-12-12 12:12:11";
// 1、创建简单日期格式化对象 , 指定的时间格式必须与被解析的时间格式一模一样,否则程序会出bug.
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//在此处程序也会提醒你格式一定要正确
Date d2 = sdf2.parse(dateStr);
}

Calendar类

代表的是系统此刻时间对应的日历,通过它可以单独获取、修改时间中的年、月、日、时、分、秒等。

常用方法:

方法名 说明
public static Calendar getInstance() 获取当前日历对象
public int get(int field) 获取日历中的某个信息
public final Date getTime() 获取日期对象
public long getTimeInMillis() 获取时间毫秒值
public void set(int field, int value) 修改日历的某个信息
public void add(int field, int amount) 为某个信息增加/减少指定的值

JDK8新增的日期类

因为在JDK8之前,传统的时间API存在存在如下问题:

  1. 一些设计上的不合理,使用不方便的问题,所以很多也都被淘汰了。
  2. 同时传统的时间API都是可变对象,修改后会丢失最开始的时间信息。
  3. 线程不安全
  4. 只能精确到毫秒

JDK8开始之后新增的时间API着手解决了这些问题:

  1. 设计更合理,功能丰富,使用更方便。

  2. 都是不可变对象,修改后会返回新的时间对象,不会丢失最开始的时间。

  3. 线程安全。

  4. 能精确到毫秒、纳秒

Arrays类

Arrays是操作数组的工具类,它可以很方便的对数组中的元素进行遍历、拷贝、排序等操作。

下面我们用代码来演示一下:遍历、拷贝、排序等操作。需要用到的方法如下

方法名 说明
public static String toString(类型 arr) 返回数组的内容
public static intl] copyofRange(类型Iarr, 起始索引, 结束索引) 拷贝数组(指定范围)
public static copyof(类型 arr, int newLength) 拷贝数组
public static setAll(doublell array, IntToDoubleFunction generator) 把数组中的原数据改为新数据
public static void sort(类型arr) 对数组进行排序(默认是升序排序)

然我们来看一下示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class ArraysTest1 {
public static void main(String[] args) {
// 1、public static String toString(类型[] arr): 返回数组的内容
int[] arr = {10, 20, 30, 40, 50, 60};
System.out.println(Arrays.toString(arr));

// 2、public static 类型[] copyOfRange(类型[] arr, 起始索引, 结束索引) :拷贝数组(指定范围,包前不包后)
int[] arr2 = Arrays.copyOfRange(arr, 1, 4);
System.out.println(Arrays.toString(arr2)); //输出:[20, 30, 40]

// 3、public static copyOf(类型[] arr, int newLength):拷贝数组,可以指定新数组的长度。
int[] arr3 = Arrays.copyOf(arr, 10);
System.out.println(Arrays.toString(arr3));

// 4、public static setAll(double[] array, IntToDoubleFunction generator):把数组中的原数据改为新数据又存进去。
double[] prices = {99.8, 128, 100};
// 0 1 2
// 把所有的价格都打八折,然后又存进去。
Arrays.setAll(prices, new IntToDoubleFunction() {
@Override
public double applyAsDouble(int value) {
// value = 0 1 2
return prices[value] * 0.8;
}
});
System.out.println(Arrays.toString(prices));

// 5、public static void sort(类型[] arr):对数组进行排序(默认是升序排序)
Arrays.sort(prices);
System.out.println(Arrays.toString(prices));
}
}

Arrays操作对象数组

刚才我们使用Arrays操作数组时,数组中存储存储的元素是int类型、double类型,是可以直接排序的,而且默认是升序排列。

如果数组中存储的元素类型是自定义的对象,如何排序呢?接下来,我们就学习一下Arrays如何对对象数组进行排序。

首先我们要准备一个Student类,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Student implements Comparable<Student>{
private String name;
private double height;
private int age;

public Student(String name, double height, int age) {
this.name = name;
this.height = height;
this.age = age;
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", height=" + height +
", age=" + age +
'}';
}
}

然后再写一个测试类,往数组中存储4个学生对象,代码如下。此时,运行代码你会发现是会报错的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ArraysTest2 {
public static void main(String[] args) {
// 目标:掌握如何对数组中的对象进行排序。
Student[] students = new Student[4];
students[0] = new Student("Josh", 169.5, 23);
students[1] = new Student("Ben", 163.8, 26);
students[2] = new Student("Ben", 163.8, 26);
students[3] = new Student("Philips", 167.5, 24);

// 1、public static void sort(类型[] arr):对数组进行排序。
Arrays.sort(students);
System.out.println(Arrays.toString(students));
}
}

报错如下:

排序报错

上面的代码为什么会报错呢?因为Arrays根本就不知道按照什么规则进行排序。为了让Arrays知道按照什么规则排序,我们有如下的两种办法。

  • 排序方式1:让Student类实现Comparable接口,同时重写compareTo方法。Arrays的sort方法底层会根据compareTo方法的返回值是正数、负数、还是0来确定谁大、谁小、谁相等。

自定义排序规则时,需要遵循的官方约定如下(升序):
如果认为左边对象 > 右边对象,应该返回正整数
如果认为左边对象 < 右边对象,应该返回负整数
如果认为左边对象 == 右边对象,应该返回整数0

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class Student implements Comparable<Student>{
private String name;
private double height;
private int age;

//...get、set、空参数构造方法、有参数构造方法...自己补全

// 指定比较规则
// this o
@Override
public int compareTo(Student o) {
// 约定1:认为左边对象 大于 右边对象 请您返回正整数
// 约定2:认为左边对象 小于 右边对象 请您返回负整数
// 约定3:认为左边对象 等于 右边对象 请您一定返回0
/* if(this.age > o.age){
return 1;
}else if(this.age < o.age){
return -1;
}
return 0;*/

//上面的if语句,也可以简化为下面的一行代码
return this.age - o.age; // 按照年龄升序排列
// return o.age - this.age; // 按照年龄降序排列
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", height=" + height +
", age=" + age +
'}';
}
}
  • 排序方式2:在调用Arrays.sort(数组,Comparator比较器);时,除了传递数组之外,传递一个Comparator比较器对象。Arrays的sort方法底层会根据Comparator比较器对象的compare方法方法的返回值是正数、负数、还是0来确定谁大、谁小、谁相等。代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class ArraysTest2 {
public static void main(String[] args) {
// 目标:掌握如何对数组中的对象进行排序。
Student[] students = new Student[4];
students[0] = new Student("Josh", 169.5, 23);
students[1] = new Student("Ben", 163.8, 26);
students[2] = new Student("Ben", 163.8, 26);
students[3] = new Student("Philips", 167.5, 24);

// 2、public static <T> void sort(T[] arr, Comparator<? super T> c)
// 参数一:需要排序的数组
// 参数二:Comparator比较器对象(用来制定对象的比较规则)
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// 制定比较规则了:左边对象 o1 右边对象 o2
// 约定1:认为左边对象 大于 右边对象 请您返回正整数
// 约定2:认为左边对象 小于 右边对象 请您返回负整数
// 约定3:认为左边对象 等于 右边对象 请您一定返回0
// if(o1.getHeight() > o2.getHeight()){
// return 1;
// }else if(o1.getHeight() < o2.getHeight()){
// return -1;
// }
// return 0; // 升序
return Double.compare(o1.getHeight(), o2.getHeight()); // 升序
// return Double.compare(o2.getHeight(), o1.getHeight()); // 降序
}
});
System.out.println(Arrays.toString(students));
}
}