Java常用类


Java常用类

字符串相关的类

String

  • String类:代表字符串。Java程序中的所有字符串字面值都作为此类的实例实现
  • String是一个final类,发表不可变得字符序列
  • 字符串是常量,用啥UN噶引号引起来表示。它们的值在创建之后不能更改
  • String对象的字符内容是存储在一个字符数组value[]中的
1
2
3
4
5
6
7
8
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence{
//The value is used for character storage.
private final char value[];

//Cache the hash code for the string.
private int hash;//Default to 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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class StringTest {
/*
String:字符串,使用一堆“”引起来表示
1.String声明为final的,不可被继承
2.String实现了Serializable接口:表示字符是支持序列化的
实现了Comparable接口:表示String可以比较大小
3.String内部定义了final char[] value用于存储字符串数据
4.String:代表不可变得字符序列。简称:不可变性。
体现:1.当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值
2.当对现有的字符串进行连接操作室,也需要重新指定内存区域赋值,不能使用原有的value进行赋值
3.当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值
5.通过字面量(区别于new)的方式给一个字符串复制,此时的字符串值生命在字符串常量池中。
6.字符串常量池中是不会存储相同内容的字符串的
*/

@Test
public void test1(){
String s1 = "abc";//字面量的定义方法
String s2 = "abc";
// s1 = "hello";

System.out.println(s1 == s2);//比较s1和s2的地址值

System.out.println(s1);
System.out.println(s2);

System.out.println("***************************************");

String s3 = "abc";
s3 += "def";
System.out.println(s3);
System.out.println(s2);

System.out.println("****************************************");

String s4 = "abc";
String s5 = s4.replace('a', 'm');
System.out.println(s4);
System.out.println(s5);
}
}
//true
//abc
//abc
//***************************************
//abcdef
//abc
//****************************************
//abc
//mbcs
  • 字符串常量池中不会创建重复的字符串的对象,将相同字符串赋值时,会优先查找已经存在的字符串,如果存在就指向它,不存在再创建

String对象的创建

1
2
3
4
5
6
7
8
9
10
11
12
String str = "hello";

//本质上this.value = new char[0];
String s1 = new String();

//this.value = original.value;
String s2 = new String(String original);

//this.value = Array.copyOf(value, value.length)
String s3 = new String(char[] a);

String s4 = new String(char[] a, int startIndex,int count);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void test2(){
//通过字面量定义的方式,此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中
String s1 = "javaEE";
String s2 = "javaEE";
//通过new + 构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值
String s3 = new String("javaEE");
String s4 = new String("javaEE");

System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s3 == s4);
}
//true
//false
//false
image-20211026173436672
  • 面试题:String s = new String(“abc”);方式创建对象,在内存中创建了几个对象?
    • 答:两个:一个是堆空间中new结构,另一个是char[]型数组对象的常量池中的数据:”abc“
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public void test3(){
String s1 = "javaEE";
String s2 = "hadoop";

String s3 = "javaEEhadoop";
String s4 = "javaEE" + "hadoop";
String s5 = s1 + "hadoop";
String s6 = "javaEE" + s2;
System.out.println(s3 == s4);
System.out.println(s3 == s5);
System.out.println(s3 == s6);
System.out.println(s5 == s6);

String s7 = s5.intern();

System.out.println(s3 == s7);
}
//true
//false
//false
//false
//true
  • 结论:
    • 常量与常量的拼接结果在常量池。且常量池不会存在相同内容的常量
    • 只要其中有一个是变量,结果就在堆中
    • 如果拼接的结果调用intern()方法,返回值就在常量池中
image-20211026184354040

String常用方法

  • intlength():返回字符串的长度:return value.length

  • char charAt(int index):返回某索引处的字符return value[index]

  • boolean isEmpty():判断是否是空字符串:return value.length == 0

  • String toLowerCase():使用默认语言环境,将String中的所有字符转换为小写

  • String toUpperCase():使用默认语言环境,将Sttring中的所有字符转换为大写

  • String trim():返回字符串的副本,忽略前导空白和尾部空白

  • boolean equals(Object obj):比较字符串的内容是否相同

  • boolean equalslgnoreCase(String anotherString):与equals方法类似,忽略大小写

  • String concat(String str):将指定字符串连接到此字符串的结尾。等价于用”+“

  • int compareTo(String anotherString):比较两个字符串的大小

  • String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串

  • String substring(int beginIndex, int endIndex):返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包括)的一个子字符串

  • boolean endWith(String suffix):测试此字符串是否以指定的后缀结束

  • boolean startWith(String prefix):测试此字符串是否以指定的前缀开始

  • boolean starsWith(String prefix, int toffest):测试此字符串从指定索引开始的子字符串是否以指定前缀开始

  • boolean contains(CharSequence s):当且仅当此字符串包含指定的char值序列时,返回true

  • int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引

  • int indexOf(String str, int fromIndex):返回指定子字符串在此字符中第一次出现处的索引,从指定的索引开始

  • int lastIndexOf(String str):返回指定子字符串中最右边出现处的索引

  • int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索

注:indexOf和lastIndexOf方法如果未找到都是返回-1

  • String replace(cahr oldChar, char newChar):返回一个新的字符串,它是通过用newChar替换此字符串中出现的所有oldChar得到的
  • String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串
  • String replaceAll(String regex, String replacement):使用给定的replacement替换此字符串所有匹配给定的正则表达式的子字符串
  • String replace First(String regex, String replacement):使用给定的replacement替换此字符串匹配给定的正则表达式的第一个字符串
  • boolean matches(String regex):告知此字符串是否匹配给定的正则表达式
  • String[] split(String regex):根据给定正则表达式的匹配拆分此字符串
  • String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中

String与基本数据类型转换

  • 字符串 => 基本数据类型、包装类

    • Integer包装类的public static int parseInt(String s):可以将由“数字”字符组成的字符串转换为整型
    • 类似的,使用java.lang包中的Byte、Short、Long、Float、Double类调相应的类方法可以将由“数字”字符组成的字符串,转化为相应的基本数据类型
    1
    2
    String str = "123";
    int num = Integer.parseInt(str);
  • 基本数据类型、包装类 => 字符串

    • 调用String类的public String value(int n )可将int型转换为字符串
    • 相应的valueOf(byte b)、valueOf(long l)、valueOf(float f)、valueOf(double d)、valueOf(boolean b)可由参数的相应类型到字符串的转换
    1
    String str1 = String.valueOf(num);

String与字符数组转换

  • 字符数组 => 字符串
    • String类的构造器:String(char[])和String(char[], int offset, int length)分别用字符数组中的全部字符和部分字符创建字符串对象
  • 字符串 => 字符数组
  • public char[] to CharArray():将字符串中的全部字符存放在一个字符数组中的方法
  • public void getCahrs(int srcBegin, int srcEnd, char[] dst,int dstBegin):提供了将指定索引范围内的字符串存放到数组中的方法
1
2
3
4
5
6
7
8
9
10
//调用String的toCharArray()方法从String -> char[]
String str = "abc123";
char [] array = str.toCharArray();
for(int i = 0; i < array.length; i++){
System.out.print(array[i]+" ");
}

//调用String的构造器从char[] -> String
char arr = new char[]{'h','e','l','l','o'};
String str1 = new String(arr);
1
2
3
4
5
6
7
8
9
10
11
//String => byte[]:调用String的getBytes()方法
public str = "abc123调用";
byte[] bytes = str.getBytes();//使用默认的字符集进行转换
System.out.println(Array.toString(bytes));

//编码:字符串 ==> 字节(看得懂 ==> 看不懂的二进制数据)
//解码:编码的逆过程(看不懂的二进制 ==> 看得懂)

//byte[] ==> String:调用String的构造器
String str1 = new String(bytes);
System.out.println(str1);

StringBuffer和StringBuilder

  • String、StringBuffer、StringBuilder三者的异同?
    • String:不可变的字符序列;底层使用char[]存储;
    • StringBuffer:可变的字符序列;线程安全的,效率偏低;底层使用char[]存储;
    • StringBuilder:可变的字符序列;JDK5.0新增,线程不安全,效率高;底层使用char[]存储;
    • 源码分析:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
String str = new String();//new char[0]
String str1 = new String("abc");//new char[]{'a','b','c'}

StringBuffer sb1 = new StringBuffer();//char[] value = new char[16];底层创建了一个长度时是16的数组
sb1.append('a');//value[0] = 'a'
sb1.append('b');//value[1] = 'b'

StringBuffer sb2 = new StromgNiffer("abc");//char[] value = new char["abc".length()+16]
/*问题1:System.out.println(sb2.length())输出什么?
答:3
问题2:扩容问题:如果要添加的数据底层数组盛不下了,那就需要扩容底层的数组
默认情况下,扩容为原来容量的2倍+2,同时将原有的数组中的元素复制到新的数组中
指导意义:在开发中建议大家使用StringBuffer构造器
*/
  • StringBuffer类的常用方法

    • StringBuffer append(xxx):提供了很多的append()方法,用于进行字符串拼接
    • StringBuffer delete(int start, int end):删除指定位置的内容
    • StringBuffer replace(int start, int end, String str):把[start,end)位置替换为str
    • StringBuffer insert(int offset, xxx):在指定位置插入xxx
    • StringBuffer reverse():把当前字符序列逆转
    • 当append和insert时,如果原来的value数组长度不够,可扩容
    • 如上这些方法支持方法链操作
    • 方法链原理:
    1
    2
    3
    4
    public StringBuilder append(String str){
    super.append(str);
    return this;
    }
    • public int indexOf(String str):返回字符串在当前StringBuffer中的位置
    • public String substring(int start, int end):返回从start开始到end结束的左闭右开区间的子字符串
    • public int length():返回StringBuffer长度
    • public char charAt(int n ):返回索引位置的字符
    • public void setCharAt(int n, char ch):将指定位置字符变成想要的字符
    • 总结:
      • 增:append(xxx)
      • 删:delete(int start, int end)
      • 改:setCharAt(int n, char ch)/replace(int start, int end, String str)
      • 查:charAt(int n)
      • 插:insert(int offset, xxx)
      • 长度:length()
      • 遍历:for()+charAt()
  • String、StringBuffer、StringBuilder三者的效率

    • 从高到低排序:StringBuffer > StringBuffer > String

常见String算法题目

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package Intermediate.oftenClass.String;

import org.junit.Test;

import java.util.Arrays;

public class test {

//1.模仿一个trim方法,去除字符串两端的空格
@Test
public void test1(){
String str = " asdasd ";
char[] array = str.toCharArray();
char[] array1 = new char[array.length];
int index = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] != ' '){
array1[index] = array[i];
index++;
}
}

String str1 = new String(array1);
System.out.println(str1);
}

//2.将一个字符串进行反转。将字符串中指定部分进行反转。比如"abcdefg"反转为”abfedcg“
@Test
public void test2(){
String str = "abcdefghijklmn";
str = reverseString(str,3,7);
System.out.println(str);
}
public String reverseString(String str, int startIndex, int endIndex){
char[] array = str.toCharArray();
char flag = ' ';
int end = endIndex;
for (int i = startIndex+1; i < endIndex; i++) {
flag = array[i];
array[i] = array[endIndex];
array[endIndex] = flag;
endIndex--;
}
return new String(array);
}


//3.获取一个字符串在领啊一个字符串中出现的次数
//比如:获取“ab”在“abkkcadkabkebfkabkskab”中出现的次数
@Test
public void test3(){
String str = "abkkcadkabkebfkabkskab";
int num = howMany(str,"a");
System.out.println(num);
}

public int howMany(String str, String need){
char[] array = str.toCharArray();
char[] resume = need.toCharArray();
int flag = 0;
int num = 0;
for (int i = 0; i < array.length; i++) {
flag = 0;
if (array[i] == resume[flag]){
for (int j = i; j < i+resume.length; j++) {
if (array[j] == resume[flag]){
flag++;
if (flag == resume.length){
num++;
}
continue;
}else if (array[j] != resume[flag]){
break;
}
}
}

}


return num;
}


//4.获取两个字符串中最大的相同子串
@Test
public void test4(){
String mainStr = "abcwzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzerthelloaavvyuiodef";
String str = "cvhelloaavvbnzzzzzzzzzzzzzzzzzzzzzzzzzzzzm";
String maxLongStr = maxLongString(mainStr,str);
System.out.println(maxLongStr);

}
public String maxLongString(String longString, String shortString) {
if (longString != null && shortString != null) {
String mainStr = ((longString.length() >= shortString.length()) ? longString : shortString);
String str = ((longString.length() < shortString.length()) ? longString : shortString);
for (int i = 0; i < str.length(); i++) {
for (int x = 0, y= str.length()-i; y<str.length(); x++, y++) {
String subStr = str.substring(x, y);
if (mainStr.contains(subStr)) {
return subStr;
}
}
}


}
return null;
}


//5.对字符串中字符进行自然顺序排序
@Test
public void test5(){
String str = "89127lknasdfzx";
String sortStr = stringArraySort(str);
System.out.println(sortStr);

}
public String stringArraySort(String str){
char[] array = str.toCharArray();
Arrays.sort(array);
return new String(array);
}



}

JDK8之前日期时间API

java.lang.System类

  • System类提供的public static long currentTimeMillis()用来返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差,通常称为时间戳

    • 此方法适用于时间差
    1
    2
    3
    4
    5
    6
    public void test1(){
    //返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差
    long time = System.currentTimeMillis();
    System.out.println(time);
    }
    //1635321191487
  • 计算世界时间的主要标准有:

  • UTC(Coordinated Universal Time)

  • GMT(Greenwich Mean Time)

  • CST(Central Standard Time)

  • java.util.Date类

    • 表示特定的瞬间,精确到毫秒
    • 构造器:
      • Date():使用无参构造器创建的对象可以获取本地当前时间
      • Date(long date):
    • 常用方法
      • getTime():返回自1970年1月1日 00:00:00 GMT以来此Date对象表示的毫秒数
      • toString():把此Date对象转换为以下形式的String:dow mon dd hh:mm:ss zzz yyyy 其中:dow是一周中的某一天(Sun,Mon,Tue,Wed,Thu,Fri,Sat),zzz是时间标准
      • 其他很多方法都过时了
    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    public class TimeDate {

    @Test
    public void test2(){
    /*
    java.util.Date类
    |---java.sql.Date类
    1.两个构造器的使用

    2.两个方法的使用
    >toString():显示当前年月日时分秒
    >getTime():获取当前Date对象对应的毫秒数(时间戳)

    3.java.sql.Date对应着数据库中的日期类型的变量
    >如何实例化
    >如何将java.util.Date对象转化为java.sql.Date对象
    */

    //构造器1
    Date date = new Date();
    System.out.println(date);
    System.out.println(date.toString());

    System.out.println(date.getTime());

    //构造器2:创建指定毫秒数的Date对象
    Date date1 = new Date(1635322036032L);
    System.out.println(date1.toString());

    //创建java.sql.Date对象
    java.sql.Date date2 = new java.sql.Date(1635322036032L);
    System.out.println(date2);
    //将java.util.Date对象转化为java.sql.Date对象
    //情况一:
    //Date date3 = new java.sql.Date(1635322036032L);
    //java.sql.Date date4 = (java.sql.Date) date3;
    //情况二:
    Date date5 = new Date();
    java.sql.Date date6 = new java.sql.Date(date5.getTime());// 直接传入时间戳

    }

    @Test
    public void test1(){
    //返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差
    long time = System.currentTimeMillis();
    System.out.println(time);

    }
    }

java.text.SimpleDateFormat类

  • Date类的API不易于国际化,大部分被废弃了,java.text.SimpleDateFormat类是一个不与语言环境有关的方式来格式化和解析日期的具体类
  • 它允许进行格式化:日期 => 文本、解析:文本 => 日期
  • 格式化:
    • SimpleDateFormat():默认的模式和语言环境创建对象
    • public SimpleDateFormat(String pattern):该构造方法可以用参数pattern指定的格式创建一个对象,该对象调用:
      • public String format(Date date):方法格式化时间对象date
  • 解析:
    • public Date parse(String source):从给定字符串的开始解析文本,以生成一个日期
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public class TimeDateTest {
/*
SimpleDateFormat的使用:SimpleDateFormat对日期Date类的格式化和解析
1.两个操作:
1.1格式化:日期--->字符串
1.2解析:格式化的逆过程,字符串--->日期
2.SimpleDateFormat的实例化
*/

@Test
public void testSimpleDateFormat() throws ParseException {
//实例化SimpleDateFormat:使用默认的构造器
SimpleDateFormat simpleDateFormat = new SimpleDateFormat();

//格式化:日期--->字符串
Date date = new Date();
System.out.println(date);

String format = simpleDateFormat.format(date);
System.out.println(format);

//解析:格式化的逆过程,字符串--->日期
String str = "21-10-28 上午3:00";
Date parse = simpleDateFormat.parse(str);
System.out.println(parse);

//------------------按指定的方式格式化和解析:调用带参数的构造器----------------------------

//实例化SimpleDateFormat:使用带参数的构造器,可以指定格式
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyyy.MMMMM.dd GGG hh:mm:ss");
SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
//格式化
String format1 = simpleDateFormat1.format(date);
String format2 = simpleDateFormat2.format(date);
System.out.println(format1);
System.out.println(format2);
//解析:要求字符串必须符合SimpleDateFormat识别的模式(通过构造器参数体现),否则就会抛出异常
Date parse1 = simpleDateFormat2.parse(format2);
System.out.println(parse1);
}
}
//Thu Oct 28 15:26:44 CST 2021
//21-10-28 下午3:26
//Thu Oct 28 03:00:00 CST 2021
//02021.十月.28 公元 03:26:44
//2021-10-28 03:26:44
//Thu Oct 28 03:26:44 CST 2021

//练习一:字符串“2021-10-28”转换为java.sql.Date
@Test
public void test1() throws ParseException {
String birth = "2021-10-28";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date parse = simpleDateFormat.parse(birth);
java.sql.Date date = new java.sql.Date(parse.getTime());
System.out.println(date);
}

//练习二:“三天打鱼两天晒网” 1990-1-1 xxxx-xx-xx是在打鱼还是在晒网
//如:2021-10-28
@Test
public void test2() throws ParseException {
String startDay = "1990-1-1";
String endDay = "2021-10-28";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date parse = simpleDateFormat.parse(startDay);
Date parse1 = simpleDateFormat.parse(endDay);
long allDay = parse1.getTime()-parse.getTime();
long day = 360000*5;
switch ((int) (allDay%day)){
case 1:
case 2:
case 3:
System.out.println("在打鱼");
break;
case 4:
case 0:
System.out.println("在晒网");
break;

}

java.util.Calendar(日历)类

  • Calendar是一个抽象基类,主要用于完成日期字段之间相互操作的功能
  • 获取Calendar实例的方法
    • 使用Calendar.getInstance()方法
    • 调用它的子类GregorianCalendar的构造器
  • 一个Calendar的实例是系统时间的抽象表示,通过get(int field)方法来取得想要的时间信息。比如YEAR、MONTH、DAY_OF_WEEK、HOUR_OF_DAY、MINUTE、SECOND
    • public void set(int field, int value)
    • public void add(int field, ing amount)
    • public final Date getTime()
    • public final void setTime(Date date)
  • 注意:
    • 获取月份时:一月是0,二月是1,以此类推,十二月是11
    • 获取星期时:周日是1,周一是2,以此类推,周六是7
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
@Test
public void voidCalendar(){
//1.实例化
//方式一:创建其子类(GregorianCalendar)对象
//方拾二:调用其静态方法getInstance()
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getClass());

/*
2.常用方法:
get()
set()
add()
getTime()
setTime()
*/

//get()
int days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));

//set()
calendar.set(Calendar.DAY_OF_MONTH,11);
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);

//add(),在某天天数上加上多少天
calendar.add(Calendar.DAY_OF_MONTH,3);
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);

//getTime():日历类--->Date,对应自己改了之后的日期
Date time = calendar.getTime();
System.out.println(time);

//setTime():Date--->日历类
Date date = new Date();
calendar.setTime(date);
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);


}
//class java.util.GregorianCalendar
//28
//301
//11
//14
//Thu Oct 14 16:24:53 CST 2021
//28

JDK8中新日期时间API

LocalDate、LocalTime、LocalDateTime

  • Java8吸收了Joda-Time的精华以一个新的开始为Java创建优秀的API。新的java.time中包含了所有关于本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类。历史悠久的Date新增了toInstant()方法,用于把Date转换成新的表示形式。这些新增的本地化时间日期API大大简化了日期时间和本地化的管理

  • LocalDate、LocalTime、LocalDateTime类是其中较重要的几个类,它们的实例是不可变得对象,分别表示使用ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单地本地日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息

    • LocalDate代表IOS格式(yyyy-MM-dd)的日期,可以存储生日,纪念日的日期
    • LocalTime表示一个时间,而不是日期
    • LocalDateTime是用来表示日期和时间的,这是一个最常用的类之一
image-20211028181150053
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/*
LocalDate,LocalTime,LocalDateTime
1.LocalDateTime比LocalDate和LocalTime用的频率高
2.类似于前面的Calendar
*/

@Test
public void test1(){

//now():获取当前的日期、时间、日期和时间
LocalDate localDate = LocalDat e.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDate);
System.out.println(localTime);
System.out.println(localDateTime);

//of():设置年、月、日、时、分、秒
LocalDateTime localDateTime1 = LocalDateTime.of(2021,10,28,10,10,10);
System.out.println(localDateTime1);

//getxxx():获取相关属性
System.out.println(localDateTime.getDayOfMonth());
System.out.println(localDateTime.getMonth());
System.out.println(localDateTime.getMinute());

//体现不可变性
//withxxx():修改相关属性
LocalDate localDate1 = localDate.withDayOfMonth(22);
System.out.println(localDate);
System.out.println(localDate1);
LocalDateTime localDateTime2 = localDateTime.withHour(5);
System.out.println(localDateTime);
System.out.println(localDateTime2);

//plusxxx():增加相关属性
LocalDateTime localDateTime3 = localDateTime.plusMonths(3);
System.out.println(localDate);
System.out.println(localDateTime3);

//minusxxx():减少相关属性
LocalDateTime localDateTime4 = localDateTime.minusDays(10);
System.out.println(localDateTime);
System.out.println(localDateTime4);
}
//2021-10-28
//18:27:34.465
//2021-10-28T18:27:34.465
//2021-10-28T10:10:10
//28
//OCTOBER
//27
//2021-10-28
//2021-10-22
//2021-10-28T18:27:34.465
//2021-10-28T05:27:34.465
//2021-10-28
//2022-01-28T18:27:34.465
//2021-10-28T18:27:34.465
//2021-10-18T18:27:34.465

瞬时:Instant

  • Instant:时间线上的一个瞬间点,这可能被用来记录应用程序中的事件时间戳
  • java.time包通过值类型Instant提供机器视图,不提供处理人类意义上的时间单位。Instant表示时间线上的一点,而不需要任何上下文信息,例如,时区。概念上讲,它只是简单的表示自1970年1月1日0时0分0秒(UTC)开始的秒数。因为java.time包是基于纳秒计算的,所以Instant的精度可以达到纳秒级
  • (1ns = 10^-9s) 1秒 = 1000毫秒 = 10^6微秒 = 10^9纳秒

image-20211028184159514

image-20211028184236813

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
/*
Instant的使用
*/

@Test
public void Instant(){
//now():获取本初子午线对应的标准时间
Instant now = Instant.now();
System.out.println(now);

//添加时间的偏移量
OffsetDateTime offsetDateTime = now.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime);

//获取对应的毫秒数,从1970年1月1日0分0时0秒UTC开始 Epoch:纪元,时代 -->Date类的getTime()
long l = now.toEpochMilli();
System.out.println(l);

//通过给定的毫秒数获取Instant实例 -->Date(long millis)
Instant instant = Instant.ofEpochMilli(l);
System.out.println(instant);

}
//2021-10-28T10:51:47.333Z
//2021-10-28T18:51:47.333+08:00
//1635418307333
//2021-10-28T10:51:47.333Z

java.time.format.DateTimeFormatter类

  • 该类提供了三种格式化方法:

    • 预定义的标准格式,如:

      • ISO_LOCAL_DATE_TIME
      • ISO_LOCAL_DATE
      • IOS_LOCAL_TIME
    • 本地化相关的格式。如:

      • oflocalizedDateTime(FirnatStyle.LONG)
    • 自定义的格式。如:

      • ofPattern (“yyyy-MM-dd hh:mm:ss E”)
      image-20211028185440626
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
36
37
38
39
40
41
42
43
44
45
46
47
/*
DateTimeFormatter:格式化或解析日期、时间
类似于simpleTimeFormat
*/

@Test
public void dateTimeFormatter(){
//方式一:预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
//格式化:日期-->字符串
LocalDateTime localDateTime = LocalDateTime.now();
String str1 = formatter.format(localDateTime);
System.out.println(localDateTime);
System.out.println(str1);
//解析:字符串-->日期
TemporalAccessor parse = formatter.parse(str1);
System.out.println(parse);


//方拾二:本地化相关的格式。如:ofLocalizedDateTime(FormatStyle.LONG)
//FormatStyle.LONG/FormatStyle.MEDIUM/FormatStyle.SHORT:适用于LocalDateTime
DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
//格式化
String str2 = formatter1.format(localDateTime);
System.out.println(str2);
//解析
TemporalAccessor parse1 = formatter1.parse(str2);
System.out.println(parse1);

//自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:Ss");
//格式化
String str4 = formatter2.format (LocalDateTime.now());
System.out.println(str4);
//解析
TemporalAccessor parse2 = formatter2.parse(str4);
System.out.println(parse2);

}
/*2021-10-28T21:08:03.637
2021-10-28T21:08:03.637
{},ISO resolved to 2021-10-28T21:08:03.637
21-10-28 下午9:08
{},ISO resolved to 2021-10-28T21:08
2021-10-28 09:08:63
{SecondOfMinute=3, MicroOfSecond=600000, MinuteOfHour=8, HourOfAmPm=9, NanoOfSecond=600000000, MilliOfSecond=600},ISO resolved to 2021-10-28
*/

其他时间API

  • zoneId:该类中包含了所有的时区信息,一个时区的ID,如 Europe/Paris

  • ZonedDateTime:一个在ISO-8601日历系统时区的日期时间,如 2007-12- 03T10:15:30+01:00 Europe/Paris。

    • 其中每个时区都对应着ID,地区ID都为“{区域}/{城市}”的格式,例如: Asia/Shanghai等
  • Clock:使用时区提供对当前即时、日期和时间的访问的时钟。

  • 持续时间:Duration,用于计算两个“时间”间隔

  • 日期间隔:Period,用于计算两个“日期”间隔

  • TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整 到“下一个工作日”等操作。

  • TemporalAdjusters : 该类通过静态方法 (firstDayOfXxx()/lastDayOfXxx()/nextXxx())提供了大量的常用 TemporalAdjuster 的实现。

  • 其他的查询手册…

Java比较器

  • Java实现对象排序的方式有两种:
    • 自然排序:java.lang.Comparable
    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    package Intermediate.oftenClass.Comparre;

    import org.junit.Test;

    import java.util.Arrays;

    public class compareTest {
    /*
    一、说明:Java中的对象,正常情况下,只能进行比较: == 或 != 。不能使用 > 或 < 的
    但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小
    如何实现?使用两个接口中的任何一个Comparable或Comparator
    二、Comparable接口的使用

    */

    /*
    Comparable接口的使用举例: 自然排序
    1.像String、包装类等实现了Comparable接口,重写了compareTo(obj)方法,给出了比较两个大小对象大小的方式
    2.重写compareTo()的规则:
    如果当前对象this大于形参对象obj,则返回正整数
    如果当前对象this小于形参对象obj,则返回负整数
    如果当前对象this等于形参对象obj,则会返回0
    3.像String、包装类重写compareTo()方法以后,进行了从小到大排列
    4.对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法,在compareTo(obj)方法中指明如何排序

    */

    @Test
    public void test1(){
    String[] arr = new String[]{"AA","BB","MM","JJ","GG","DD"};

    Arrays.sort(arr);
    System.out.println(Arrays.toString(arr));
    }

    @Test
    public void test2(){
    Goods[] arr = new Goods[5];
    arr[0] = new Goods("联想Mouse",34);
    arr[1] = new Goods("戴尔Mouse",22);
    arr[2] = new Goods("小米Mouse",30);
    arr[3] = new Goods("罗技Mouse",11);
    arr[4] = new Goods("华为Mouse",11);

    Arrays.sort(arr);
    System.out.println(Arrays.toString(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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    package Intermediate.oftenClass.Comparre;

    import org.jetbrains.annotations.NotNull;

    public class Goods implements Comparable{
    private String name;
    private double price;

    public Goods() {
    }

    public Goods(String name, double price) {
    this.name = name;
    this.price = price;
    }

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public double getPrice() {
    return price;
    }

    public void setPrice(double price) {
    this.price = price;
    }

    //指明按照什么方式进行排序,按照价格从低到高排序,再按照产品名称从低到高排序
    @Override
    public int compareTo(@NotNull Object o) {
    if (o instanceof Goods){
    Goods goods = (Goods) o;
    //方式一
    if (this.price > goods.price){
    return 1;
    }else if (this.price < goods.price){
    return -1;
    }else {
    return this.name.compareTo(goods.name);
    }
    //方式二
    //return Double.compare(this.price,goods.price);
    }
    throw new RuntimeException("传入的数据类型不一致!");
    }
    }

    • 定制排序:java.util.Comparator
      • 当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,或者实现了java.langComparable接口的排序规则不适合当前的操作,那么可以考虑使用Comparator的对象来排序,强行对多个对象进行整体排序的比较
      • 重写compare(Object o1, Object o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2
      • 可以将Comparrator 传递给sort方法(如Collections.sort或Array.sort),从而允许在排序顺序上实现精确控制
      • 还可以使用Comparator来控制某些数据结构(如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序
    • Comparable接口与Comparator的使用的对比:
      • Comparable接口的方式一旦一定,保证Comparable接口实现类的对象在任何位置都可以比较大小
      • Comparator接口属于临时性的比较

System类

  • System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包

  • 由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是static的,所以可以很方便的进行调用

  • 成员变量

    • System类内部包含in、out和err三个成员变量,分别代表标准输入流(键盘输入),标准输出流(显示器)和标准错误输出流(显示器)
  • 成员方法

    • native long currentTimeMillis():该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1日0时0分0秒所差的毫秒数

    • void exit(int status):该方法的作用是退出程序。其中status的值为0代表正常退出,非零代表异常退出。使用该方法可以在图形界面编程中实现程序的退出功能等。

    • void gc():该方法的作用是请求系统进行垃圾回收。至于系统是否立刻回收,则取决于系统中垃圾回收算法的实现以及系统执行时的情况

    • String getProperty(String key):该方法的作用是获得系统中属性名为key的属性对应的值。系统中常见的属性名以及属性的作用如下表所示:

      image-20211029114056278

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
@Test
public void test(){
String javaVersion = System.getProperty("java.version");
System.out.println("java的version:" + javaVersion);
String javaHome = System.getProperty("java.home");
System.out.println("java的home:" + javaHome);
String osName = System.getProperty("os.name");
System.out.println("os的name:" + osName);
String osVersion = System.getProperty("os.version");
System.out.println("os的version:" + osVersion);
String userName = System.getProperty("user.name");
System.out.println("user的name:" + userName);
String userHome = System.getProperty("user.home");
System.out.println("user的home:" + userHome);
String userDir = System.getProperty("user.dir");
System.out.println("user的dir:" + userDir);

}

//java的version:1.8.0_31
//java的home:A:\JDK\Java\jdk1.8.0_31\jre
//os的name:Windows 8.1
//os的version:6.3
//user的name:diemo
//user的home:C:\Users\diemo
//user的dir:D:\Idea\ShangGuiGu\Study

Math类

  • java.lang.Math提供了一系列静态方法用于科学计算。其方法的参数和返回值类型一般为double型
    • abs:绝对值
    • acos,asin,atan,cos,sin,tan:三角函数
    • sqrt:平方根
    • pow(double a, double b):a的b次幂
    • log:自然对数
    • exp:e为底指数
    • max(double a, double b):求两个数的最大值
    • min(double a, double b):求两个数的最小值
    • random():返回0.0到1.0的随机数
    • long round(double a):double型数据a转换为long型(四舍五入)
    • toDegrees(double angrad):弧度 => 角度
    • toRadians(double angdeg):角度 => 弧度

BigInteger与BigDecimal

  • Integer类作为int的包装类,能存储的最大整型值为2^31-1,Long类也是有限的,最大为2^63-1。如果要表示再大的整数,不管是基本数据类型还是他们的包装类都无能为力,更不说进行运算了

  • java.math包的BigInteger可以表示不可变的任意精度的整数。BigInteger提供所有Java的基本整数操作符的对应物,并提供java.long.Math的所有相关方法。另外BigInteger还提供一下运算:模算术、GCD计算、质数测试、素数生成、位操作以及一些其他操作

  • 构造器:

    • BigInteger(String val):根据字符串构建BigInteger对象
  • 常用方法

    • public BigInteger abs():返回此 BigInteger 的绝对值的 BigInteger。
    • BigInteger add(BigInteger val) :返回其值为 (this + val) 的 BigInteger
    • BigInteger subtract(BigInteger val) :返回其值为 (this - val) 的 BigInteger
    • BigInteger multiply(BigInteger val) :返回其值为 (this * val) 的 BigInteger
    • BigInteger divide(BigInteger val) :返回其值为 (this / val) 的 BigInteger。整数 相除只保留整数部分。
    • BigInteger remainder(BigInteger val) :返回其值为 (this % val) 的 BigInteger。
    • BigInteger[] divideAndRemainder(BigInteger val):返回包含 (this / val) 后跟 (this % val) 的两个 BigInteger 的数组。
    • BigInteger pow(int exponent) :返回其值为 (thisexponent) 的 BigInteger。
  • 一般的Float类和Double类可以用来做科学计算或过程计算,但在商业计算中,要求数字精度比较高,故用到java.math.BigDecimal类

  • BigDecimal类支持不可变、任意精度的有符号十进制定点数

  • 构造器

    • public BigDecimal(double val)
    • public BigDecimal(String val)
  • 常用方法

    • public BigDecimal add(BigDecimal augend)
    • public BigDecimal subtract(BigDecimal subtrahend)
    • public BigDecimal multiply(BigDecimal multiplicand)
    • public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void test1(){

BigInteger bi = new BigInteger("12433241123");
BigDecimal bd = new BigDecimal("12435.351");
BigDecimal bd2 = new BigDecimal("11");
System.out.println(bi);
// System.out.println(bd.divide(bd2));
System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP));
System.out.println(bd.divide(bd2, 15, BigDecimal.ROUND_HALF_UP));
}

//12433241123
//1130.486
//1130.486454545454545

Author: Sans Zhu
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source Sans Zhu !
  TOC