1 String类
1.1 概述
-
String类:代表字符串。Java程序中的所有字符串字面量(如:
“abc”
)都是此类的实例。 -
String是一个final类,代表
不可变的字符序列
。 -
字符串是常量,用双引号(
“”
)引起来表示。它们的值在创建之后不能改变。 -
String对象的字符串内容是存储在一个字符数组
value[]
中的。
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 字面量的定义方式
- 示例:
package top.open1024.string.demo1;
/**
* @author open1024
* @version 1.0
* @since 2021-09-17 20:21
*/
public class Test {
public static void main(String[] args) {
// 字面量的定义方式
String s1 = "123";
String s2 = "123";
s1 = "hello";
System.out.println("s1 = " + s1); // s1 = hello
System.out.println("s2 = " + s2); // s2 = 123
}
}
1.3 String的特点
-
① 字符串String类型本身是final修饰的,意味着我们不能继承String。
-
② 字符串的对象也是不可变对象,意味着一旦进行修改,就会产生新的对象。
注意:如果程序中涉及到了大量的字符串的修改操作,那么此时的内存消耗比较高,可能需要考虑使用StringBuilder或StringBuffer的可变字符序列。
- ③ String对象内部是用字符数组保存的。
JDK 9之前是用char[]数组保存的,JDK 9之后时用byte[]数组保存的。
- 例如:下面的代码是等价的
String str = "abc";
char[] chs= {'a','b','c'};
String str = new String(chs);
-
④ String类中的char[] values数组也是用final修饰的,意味着这个数组不可变,又因为是用private修饰的,意味着外界不能直接操作它。String类提供的所有方法都是用新对象来表示修改后的内容的,保证了String对象的不可变。
-
⑤ 因为String对象设计为不可变,所以String有常量池来保存很多常量对象。
-
- 常量池在方法区。
-
- 常量池的细致划分:
-
-
- JDK 6及之前:方法区。
-
-
-
- JDK 7:堆。
-
-
-
- JDK 8:元空间。
-
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2); //true
// 内存中只有一个"abc"对象被创建,同时被s1和s2所共享
1.4 String的内存示意图
- 示例:
package top.open1024.string.demo3;
/**
* @author open1024
* @version 1.0
* @since 2021-09-18 11:05
*/
public class Test {
public static void main(String[] args) {
String str = "abc";
String str2 = new String("abc");
System.out.println(str == str2); // false
}
}
1.5 构造String对象
1.5.1 构造方法
- 初始化新创建的String对象,表示空字符序列:
public String(){}
- 初始化一个新创建的String对象,使其表示一个和参数相同的字符序列;换言之,新创建的字符串是该参数字符串的副本
public String(String original){}
- 通过当前参数中的字符数组来构造新的String:
public String(char[] value){}
- 通过字符数组的一部分来构造新的String:
public String(char[] value,int offset, int count){}
- 通过使用平台的默认字符集解码当前参数中的字节数组来构造新的String:
public String(byte[] bytes){}
- 通过使用指定的字符集解码当前参数中的字节数组来构造新的String:
public String(byte[] bytes,String charsetName){}
- 示例:
package top.open1024.string.demo4;
import java.io.UnsupportedEncodingException;
/**
* @author open1024
* @version 1.0
* @since 2021-09-19 10:37
*/
public class Test {
public static void main(String[] args) throws UnsupportedEncodingException {
// 字符串常量对象
String str = "hello";
System.out.println("str = " + str);
// 无参构造
String str1 = "";
System.out.println("str1 = " + str1);
// 创建"hello"字符串常量的副本
String str2 = new String("hello");
System.out.println("str2 = " + str2);
// 通过字符数组创建
char[] chs = {'a', 'b', 'c', 'd'};
String str3 = new String(chs);
String str4 = new String(chs, 0, 3);
System.out.println("str3 = " + str3);
System.out.println("str4 = " + str4);
// 通过字节数组构造
byte bytes[] = {97, 98, 99 };
String str5 = new String(bytes);
String str6 = new String(bytes,"utf-8");
System.out.println("str5 = " + str5);
System.out.println("str6 = " + str6);
}
}
1.5.2 静态方法
- 返回指定数组的String:
public static String valueOf(char data[]) {}
- 返回指定数组的String(指定子数组的开始索引和子数组的长度):
public static String valueOf(char data[], int offset, int count){}
- 返回各种类型的value的String:
public static String valueOf(xx value) {}
- 示例:
package top.open1024.string.demo5;
/**
* String的静态方法
*
* @author open1024
* @version 1.0
* @since 2021-09-19 19:01
*/
public class Test {
public static void main(String[] args) {
char[] chs = {'A', 'B', '我', '是', '谁'};
String s = String.valueOf(chs);
System.out.println("s = " + s);
String s1 = String.valueOf(chs, 0, 2);
System.out.println("s1 = " + s1);
Object obj = "你好啊";
String s2 = String.valueOf(obj);
System.out.println("s2 = " + s2);
}
}
1.5.3 使用“”
+
-
任意数据类型和
“字符串”
进行拼接,结果都是字符串。 -
示例:
package top.open1024.string.demo6;
import java.util.ArrayList;
import java.util.List;
/**
* @author open1024
* @version 1.0
* @since 2021-09-19 19:25
*/
public class Test {
public static void main(String[] args) {
int num = 123456;
String s = num + "";
System.out.println("s = " + s);
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
String str = list + "";
System.out.println(str);
}
}
1.6 字符串拼接问题
1.6.1 拼接结果的存储和比较问题
-
原则:
-
- 常量+常量:结果是常量池。
-
- 常量和变量 或 变量和变量:结果是堆。
-
- 拼接后调用intern方法:结果在常量池。
-
示例:
package top.open1024.string.demo7;
/**
* @author open1024
* @version 1.0
* @since 2021-09-19 19:52
*/
public class Test {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
String s4 = (s1 + "world").intern(); // 将拼接的结果放在常量池中
String s5 = (s1 + s2).intern();
System.out.println(s3 == s4); // true
System.out.println(s3 == s5); // true
}
}
- 示例:
package top.open1024.string.demo8;
/**
* @author open1024
* @version 1.0
* @since 2021-09-19 19:57
*/
public class Test {
public static void main(String[] args) {
final String s1 = "hello";
final String s2 = "world";
String s3 = "helloworld";
String s4 = s1 + "world"; // s1是常量,"world"也是常量,所以s4是常量
String s5 = s1 + s2; // s1是常量,s2是常量,所以s5是常量
String s6 = "hello" + "world"; // "hello"是常量,"world"是常量,所以s6是常量
System.out.println(s3 == s4); // true
System.out.println(s3 == s5); // true
System.out.println(s3 == s6); // true
}
}
- 示例:
package top.open1024.string.demo9;
/**
* @author open1024
* @version 1.0
* @since 2021-09-19 20:00
*/
public class Test {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
String s4 = s1 + "world"; // s1是变量,"world"是常量,所以s4是变量
String s5 = s1 + s2; // s1是变量,s2是变量,所以s5是变量
String s6 = "hello" + "world"; // "hello"是常量,"world"是常量,所以s6是常量
System.out.println(s3 == s4); // false
System.out.println(s3 == s5); // false
System.out.println(s3 == s6); // true
}
}
1.6.2 拼接效率问题
- 示例:
package top.open1024.string.demo10;
/**
* @author open1024
* @version 1.0
* @since 2021-09-19 20:03
*/
public class Test {
public static void main(String[] args) {
String str = "0";
for (int i = 0; i < 5; i++) {
str += i;
}
System.out.println("str = " + str);
}
}
- 不过,现在的JDK版本,都会使用可变字符序列对如上的代码优化,不信,反编译查看字节码:
javap -c Test.class
Compiled from "Test.java"
public class top.open1024.string.demo10.Test {
public top.open1024.string.demo10.Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String 0
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: iconst_5
7: if_icmpge 35
10: new #3 // class java/lang/StringBuilder
13: dup
14: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
17: aload_1
18: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: iload_2
22: invokevirtual #6 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
25: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
28: astore_1
29: iinc 2, 1
32: goto 5
35: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
38: new #3 // class java/lang/StringBuilder
41: dup
42: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
45: ldc #9 // String str =
47: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
50: aload_1
51: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
54: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
57: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
60: return
}
1.6.3 concat方法拼接
-
concat()方法拼接,哪怕是两个常量对象拼接,结果也是在堆中。
-
示例:
package top.open1024.string.demo19;
/**
* @author open1024
* @version 1.0
* @since 2021-09-21 08:43
*/
public class Test {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
String s4 = "hello".concat("world");
String s5 = "hello" + "world";
System.out.println(s3 == s4); // false
System.out.println(s3 == s5); // true
System.out.println(s1 + s2 == s5); // false
}
}
1.7 字符串对象的比较
1.7.1 ==
-
==
比较的是对象的地址,只有两个字符串变量都指向字符串的常量对象时,才会返回true。 -
示例:
package top.open1024.string.demo20;
/**
* @author open1024
* @version 1.0
* @since 2021-09-21 08:47
*/
public class Test {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); // true
String s3 = new String("hello");
String s4 = new String("hello");
System.out.println(s3 == s4); // false
System.out.println(s1 == s4); // false
}
}
1.7.2 equals()方法
- equals()方法比较的是对象的内容,因为String类重写了equals()方法,并且equals()方法区分大小写:
public boolean equals(Object anObject){}
- 示例:
package top.open1024.string.demo21;
/**
* @author open1024
* @version 1.0
* @since 2021-09-21 08:51
*/
public class Test {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "hello";
System.out.println(s1.equals(s2)); // true
String s3 = new String("hello");
String s4 = new String("hello");
System.out.println(s3.equals(s4)); // true
System.out.println(s1.equals(s4)); // true
}
}
1.7.3 equalsIgnoreCase()方法
- equalsIgnoreCase()方法比较的是对象的内容,并且不区分大小写:
public boolean equalsIgnoreCase(String anotherString){}
- 示例:
package top.open1024.string.demo22;
/**
* @author open1024
* @version 1.0
* @since 2021-09-21 08:55
*/
public class Test {
public static void main(String[] args) {
String s1 = new String("hello");
String s2 = new String("HELLO");
System.out.println(s1.equalsIgnoreCase(s2)); // true
}
}
1.7.4 compareTo()方法
- String类重写了Comparable接口的抽象方法,自然排序,按照字符的Unicode编码值进行比较大小,严格区分大小写:
public int compareTo(String anotherString){}
- 示例:
package top.open1024.string.demo23;
/**
* @author open1024
* @version 1.0
* @since 2021-09-21 08:58
*/
public class Test {
public static void main(String[] args) {
String s1 = "i";
String s2 = "love";
System.out.println(s1.compareTo(s2)); // -3
}
}
1.7.5 compareToIgnoreCase()方法
- compareToIgnoreCase()方法不区分大小写,其他按照字符的Unicode编码值进行比较大小:
public int compareToIgnoreCase(String str){}
- 示例:
package top.open1024.string.demo24;
/**
* @author open1024
* @version 1.0
* @since 2021-09-21 09:00
*/
public class Test {
public static void main(String[] args) {
String s1 = new String("hello");
String s2 = new String("Hello");
System.out.println(s1.compareToIgnoreCase(s2)); // 0
}
}
1.8 空字符串的比较
1.8.1 那些是空字符串
-
空字符串的长度是0。
-
示例:
package top.open1024.string.demo25;
/**
* 空字符串
*
* @author open1024
* @version 1.0
* @since 2021-09-21 10:54
*/
public class Test {
public static void main(String[] args) {
String s1 = "";
String s2 = new String();
String s3 = new String("");
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
}
}
1.8.2 如何判断某个字符串是否为空字符串?
- 示例:
package top.open1024.string.demo26;
/**
* @author open1024
* @version 1.0
* @since 2021-09-21 10:56
*/
public class Test {
public static void main(String[] args) {
String str = "";
if ("".equals(str)) {
System.out.println("是空字符串");
}
}
}
- 示例:
package top.open1024.string.demo27;
/**
* @author open1024
* @version 1.0
* @since 2021-09-21 10:57
*/
public class Test {
public static void main(String[] args) {
String str = "";
if (null != str && str.isEmpty()) {
System.out.println("是空字符串");
}
}
}
- 示例:
package top.open1024.string.demo28;
/**
* @author open1024
* @version 1.0
* @since 2021-09-21 10:58
*/
public class Test {
public static void main(String[] args) {
String str = "";
if(null != str && str.equals("")){
System.out.println("是空字符串");
}
}
}
- 示例:
package top.open1024.string.demo29;
/**
* @author open1024
* @version 1.0
* @since 2021-09-21 10:59
*/
public class Test {
public static void main(String[] args) {
String str = "";
if(null != str && str.length() ==0){
System.out.println("是空字符串");
}
}
}
1.9 字符串的常用方法
1.9.1 系列1
- 字符串是否为空:
public boolean isEmpty() {}
- 返回字符串的长度:
public int length() {}
- 拼接,等价于
+
:
public String concat(String str) {}
- 比较字符串是否相等,区分大小写:
public boolean equals(Object anObject){}
- 比较字符串是否相等,不区分大小写:
public boolean equalsIgnoreCase(String anotherString){}
- 比较字符串大小,区分大小写,按照Unicode编码值比较大小:
public int compareTo(String anotherString){}
- 比较字符串大小,不区分大小写,按照Unicode编码值比较大小:
public int compareToIgnoreCase(String str){}
- 将字符串中大写字母转为小写:
public String toLowerCase(){}
- 将字符串中小写字母转为大写:
public String toUpperCase(){}
- 去掉字符串前后空白符:
public String trim(){}
- 示例:
package top.open1024.string2.demo;
/**
* @author open1024
* @version 1.0
* @since 2021-09-24 14:10
*/
public class Test {
public static void main(String[] args) {
String str = "hello world";
String s = str.toUpperCase();
System.out.println("将字符串中的小写字母转换为大写字母 = " + s);
String str2 = "Hello WorLD";
String s1 = str2.toLowerCase();
System.out.println("将字符串中的大写字母转换为小写字母 = " + s1);
String str3 = " hello world ";
String s3 = str3.trim();
System.out.println("去掉字符串前后空白符 = " + s3);
}
}
1.9.2 系列2:查找
- 字符串中是否包含子串:
public boolean contains(CharSequence s){}
- 从前往后查找字符串中的子串,如果有,有返回第一次出现的下标;否则,返回-1:
public int indexOf(String str){}
- 从后往前查找字符串中的子串,如果有,有返回第一次出现的下标;否则,返回-1:
public int lastIndexOf(String str){}
- 示例:
package top.open1024.string2.demo2;
/**
* @author open1024
* @version 1.0
* @since 2021-09-24 14:17
*/
public class Test {
public static void main(String[] args) {
String str = "hello world";
String str2 = "or";
boolean contains = str.contains(str2);
if (contains) {
System.out.println(str + "中是否包含" + str2);
}
int index = str.indexOf(str2);
System.out.println(str2 + "在" + str + "中从前往后查找的索引是:" + index);
index = str.lastIndexOf(str2);
System.out.println(str2 + "在" + str + "中从后往前的索引是:" + index);
}
}
1.9.3 系列3:字符串截取
- 返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串:
public String substring(int beginIndex){}
- 返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串:
public String substring(int beginIndex, int endIndex) {}
- 示例:
package top.open1024.string2.demo3;
/**
* @author open1024
* @version 1.0
* @since 2021-09-24 14:24
*/
public class Test {
public static void main(String[] args) {
String str = "Java is a good computer language";
System.out.println(str.substring(5)); // is a good computer language
System.out.println(str.substring(5, 11)); // is a g
}
}
1.9.4 系列4:和字符相关
- 返回index位置的字符:
public char charAt(int index){}
- 将此字符串转换为一个新的字符数组返回:
public char[] toCharArray(){}
- 返回指定数组中表示该字符序列的String:
public String(char value[]){}
- 返回指定数组中表示该字符序列的 String:
public String(char value[], int offset, int count){}
- 返回指定数组中表示该字符序列的 String:
public static String copyValueOf(char data[]){}
- 返回指定数组中表示该字符序列的 String:
public static String valueOf(char data[], int offset, int count){}
- 返回指定数组中表示该字符序列的 String:
public static String valueOf(char data[]){}
- 示例:
package top.open1024.string2.demo4;
import java.util.Arrays;
/**
* @author open1024
* @version 1.0
* @since 2021-09-24 14:27
*/
public class Test {
public static void main(String[] args) {
// 将首字母抓换为大写
String str = "hello World";
str = Character.toUpperCase(str.charAt(0)) + str.substring(1);
System.out.println("str = " + str); // Hello World
// 将字符串中的字符按照大小顺序排列
String str2 = "helloworldjava";
char[] chars = str2.toCharArray();
Arrays.sort(chars);
System.out.println("chars = " + Arrays.toString(chars)); // [a, a, d, e, h, j, l, l, l, o, o, r, v, w]
}
}
1.9.5 系列5:编码和解码
- 编码,将字符串转换为字节数组,按照平台默认的字符编码进行编码:
public byte[] getBytes(){}
- 编码,按照指定的编码方式进行编码:
public byte[] getBytes(Charset charset){}
- 解码,将字节数组转换为字符串,按照平台默认的字符编码进行解码:
public String(byte bytes[]) {}
public String(byte bytes[], int offset, int length){}
- 解码,按照指定的编码方式进行解码:
public String(byte bytes[], Charset charset){}
public String(byte bytes[], String charsetName) throws UnsupportedEncodingException{}
- 示例:
package top.open1024.string2.demo5;
import java.nio.charset.StandardCharsets;
/**
* @author open1024
* @version 1.0
* @since 2021-09-24 14:43
*/
public class Test {
public static void main(String[] args) {
String str = "我爱中国";
System.out.println(new String(str.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8));
}
}
1.9.6 系列6:开头和结尾
- 是否以指定字符串开头:
public boolean startsWith(String prefix){}
public boolean startsWith(String prefix, int toffset){}
- 是否以指定字符串结尾:
public boolean endsWith(String suffix){}
- 示例:
package top.open1024.string2.demo6;
/**
* @author open1024
* @version 1.0
* @since 2021-09-24 14:46
*/
public class Test {
public static void main(String[] args) {
String str = "我爱中国,我喜欢Java语言,但是我的英语不咋的";
System.out.println(str.startsWith("我")); // true
System.out.println(str.startsWith("我爱")); // true
System.out.println(str.startsWith("我爱中国")); // true
System.out.println(str.endsWith("不咋的")); // true
System.out.println(str.endsWith("咋的")); // true
System.out.println(str.endsWith("的")); // true
}
}
1.9.7 系列7:正则表达式
-
正则表达式:用来专门处理字符串的技术。
-
字符类:
-
[abc]
:只能是a或b或c。
-
[^abc]
:除了a、b、c以外的任意一个字符。
-
[a-zA-Z]
:必须是a-z,A-Z中的任意一个字符。
-
[^a-zA-Z]
:除了a-z,A-Z中的任意任意一个字符。
-
数字类:
-
[0-9]
:只能是0和9之间的任意一个数字。
-
\d
:等同于[0-9]
。
-
[^0-9]
:除了0和9之间的任意一个数字。
-
\D
:等同于[^0-9]
。
-
预定于字符类:
-
.
:匹配所有字符。
-
\d
:等同于[0-9]
。
-
\D
:等同于[^0-9]
。
-
\w
:等同于[a-zA-Z_0-9]
。
-
\W
:等同于[^a-zA-Z_0-9]
。
-
边界匹配器:
-
^
:行的开头。
-
$
:行的结尾。
-
数量类:
-
X?
:X字符最多只能出现一次(0次或1次)。
-
X*
:X字符可以出现0次、1次或多次。
-
X+
:X字符可以出现1次或多次。
-
X{n}
:X字符只能出现n次。
-
X{n*,}
:x字符至少出现n次(在数学中表示[n,+∞))。
-
X{n,m}
:x字符只能出现n到m次(在数学中表示[n,m])。
-
字符串是否匹配指定的正则表达式:
public boolean matches(String regex){}
- 替换,不支持正则:
public String replace(char oldChar, char newChar){}
public String replace(CharSequence target, CharSequence replacement){}
- 替换第一个匹配部分:
public String replaceFirst(String regex, String replacement){}
- 替换所有匹配部分:
public String replaceAll(String regex, String replacement){}
- 示例:
package top.open1024.string2.demo8;
/**
* 手机号码的规则:
* 开头必须是1,长度规定11。
* 第二位 3 - 9
* 第三位到最后一位 0 - 9
*
* @author open1024
* @version 1.0
* @since 2021-09-24 15:31
*/
public class Test {
public static void main(String[] args) {
String iphone = "13800138000";
boolean matches = iphone.matches("^1[3-9]\\d{9}$");
System.out.println("matches = " + matches);
}
}
- 示例:
package top.open1024.string2.demo9;
/**
* @author open1024
* @version 1.0
* @since 2021-09-24 16:28
*/
public class Test {
public static void main(String[] args) {
String str = "hello22world.java;234";
// 将其中的非字母替换掉
String s = str.replaceAll("[^a-zA-Z]", "");
System.out.println("s = " + s);
}
}
1.9.8 系列8:拆分
- 按照某种规则将字符串进行拆分:
public String[] split(String regex){}
- 示例:
package top.open1024.string2.demo10;
import java.util.Arrays;
/**
* @author open1024
* @version 1.0
* @since 2021-09-24 16:34
*/
public class Test {
public static void main(String[] args) {
String str = "张三.23|李四.24|王五.25";
// 按照|拆分
String regex = "\\|";
String[] split = str.split(regex);
for (String s : split) {
// 按照.进行拆分
String[] str2 = s.split("\\.");
System.out.println(Arrays.toString(str2));
}
}
}
1.10 练习题
1.10.1 练习1
-
在字符串中找出连续最长数字串,返回这个串的长度,并打印这个最长数字串。
-
例如:abcd12345cd125se123456789,返回9,打印出123456789。
-
示例:
package top.open1024.string2.demo11;
/**
* @author open1024
* @version 1.0
* @since 2021-09-24 16:45
*/
public class Test {
public static void main(String[] args) {
String str = "abcd12345cd125se123456789";
String[] split = str.split("[a-zA-Z]+");
String max = "";
for (String s : split) {
if (s.length() > max.length()) {
max = s;
}
}
System.out.println("最长的字符串是:" + max + ",它的长度是:" + max.length());
}
}
1.10.2 练习2
-
将字符串中指定部分进行反转。比如将“abcdefgho”反转为”abfedcgho”。
-
示例:
package top.open1024.string2.demo12;
/**
* @author open1024
* @version 1.0
* @since 2021-09-24 16:54
*/
public class Test {
public static void main(String[] args) {
String str = "abcdefgho";
String reverse = reverse(str, 2, 5);
System.out.println("reverse = " + reverse); // abfedcgho
}
public static String reverse(String str, int start, int end) {
char[] chars = str.toCharArray();
for (int i = start, j = end; i < j; i++, j--) {
char temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
}
return new String(chars);
}
}
1.10.3 练习3
-
计算字符串B(例如:ab)在字符串A(例如: dsabdnabdsnabeabiwpabekabd)中出现的次数。
-
实现思路:
-
- ① 对字符串进行索引查找 indexOf。
-
- ② 找到字符串的索引记录,进行字符串截取。
-
- ③ 直到找到位置,indexOf的方法是-1。
-
- ④ 一旦找到,计算器+1。
-
示例:
package top.open1024.string2.demo13;
/**
* @author open1024
* @version 1.0
* @since 2021-09-26 13:09
*/
public class Test {
public static void main(String[] args) {
String a = "dsabdnabdsnabeabiwpabekabd";
String b = "ab";
int times = times(a, b);
System.out.println("times = " + times);
}
/**
* 字符串出现的次数
*
* @param str 字符串A
* @param sub 字符串B
* @return 返回字符串B在字符串A中出现的次数
*/
public static int times(String str, String sub) {
int count = 0; // 计数器
int index; // 定义变量,记录字符串查找后的索引
while ((index = str.indexOf(sub)) != -1) {
// 计数器+1
count++;
// 截取字符串
str = str.substring(index + sub.length());
}
return count;
}
}
2 StringBuilder类
2.1 概述
-
因为String对象是不可变的对象,虽然可以共享常量对象,但是对于频繁字符串的修改和拼接操作,效率极低。因此,JDK又在java.lang包中提供了可变字符序列StringBuilder和StringBuffer。
-
StringBuffer:线程安全。
-
StringBuilder:线程不安全。
2.2 常用方法
- 拼接:
public StringBuilder append(StringBuffer sb){}
public StringBuilder append(CharSequence s) {}
public StringBuilder append(CharSequence s, int start, int end) {}
public StringBuilder append(char[] str){}
public StringBuilder append(char[] str, int offset, int len) {}
public StringBuilder append(boolean b){}
public StringBuilder append(char c) {}
public StringBuilder append(int i) {}
public StringBuilder append(long lng) {}
public StringBuilder append(float f){}
public StringBuilder append(double d){}
- 在index位置插入:
public StringBuilder insert(int index, char[] str, int offset,
int len){}
public StringBuilder insert(int offset, Object obj){}
public StringBuilder insert(int offset, String str) {}
public StringBuilder insert(int offset, char[] str){}
public StringBuilder insert(int dstOffset, CharSequence s) {}
public StringBuilder insert(int dstOffset, CharSequence s,
int start, int end){}
public StringBuilder insert(int offset, boolean b) {}
public StringBuilder insert(int offset, char c){}
public StringBuilder insert(int offset, int i){}
public StringBuilder insert(int offset, long l){}
public StringBuilder insert(int offset, float f){}
public StringBuilder insert(int offset, double d) {}
- 删除[start,end)之间的字符:
public StringBuilder delete(int start, int end){}
- 删除index位置字符:
public StringBuilder deleteCharAt(int index) {}
- 替换index位置字符:
public void setCharAt(int index, char ch) {}
- 反转:
public StringBuilder reverse(){}
- 设置当前字符序列的长度为newLength:
public void setLength(int newLength){}
- 替换[start,end)范围的字符序列为str:
public StringBuilder replace(int start, int end, String str){}
- 查找字符串在字符序列中的位置:
public int indexOf(String str){}
public int indexOf(String str, int fromIndex){}
public int lastIndexOf(String str){}
public int lastIndexOf(String str, int fromIndex){}
- 截取子串:
public String substring(int start){}
public String substring(int start, int end){}
- 返回此序列中的数据的字符串表示形式:
public String toString(){}
- 示例:
package top.open1024.stringbuilder.demo1;
/**
* @author open1024
* @version 1.0
* @since 2021-09-25 08:44
*/
public class Test {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("helloworld");
sb.setLength(30);
System.out.println("sb = " + sb); // sb = helloworld
}
}
- 示例:
package top.open1024.stringbuilder.demo2;
/**
* @author open1024
* @version 1.0
* @since 2021-09-25 09:20
*/
public class Test {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("helloworld");
sb.reverse();
System.out.println("sb = " + sb); // sb = dlrowolleh
}
}
- 示例:
package top.open1024.stringbuilder.demo3;
/**
* @author open1024
* @version 1.0
* @since 2021-09-25 09:21
*/
public class Test {
public static void main(String[] args) {
StringBuilder s = new StringBuilder("helloworld");
s.delete(1, 3);
s.deleteCharAt(4);
System.out.println(s); // hlowrld
}
}
- 示例:
package top.open1024.stringbuilder.demo4;
/**
* @author open1024
* @version 1.0
* @since 2021-09-25 09:22
*/
public class Test {
public static void main(String[] args) {
StringBuilder s = new StringBuilder("helloworld");
s.insert(5, "java");
s.insert(5, "open1024");
System.out.println(s);
}
}
- 示例:
package top.open1024.stringbuilder.demo5;
/**
* @author open1024
* @version 1.0
* @since 2021-09-25 09:23
*/
public class Test {
public static void main(String[] args) {
StringBuilder s = new StringBuilder();
s.append("hello").append(true).append('a').append(12).append("open1024");
System.out.println(s); // hellotruea12open1024
System.out.println(s.length()); //15
}
}
3 系统相关类
3.1 System类
3.1.1 概述
-
System类,定义在java.lang包中。
-
System类中定义了一些常用的类字段和方法,该类不能实例化。
3.1.2 常用方法
- 返回当前系统时间距离1970-1-1 0:0:0的毫秒值:
public static native long currentTimeMillis();
- 从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。常用于数组的插入和删除:
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
- 运行垃圾回收器:
public static void gc(){}
- 退出当前系统:
public static void exit(int status){}
- 获取某个系统属性:
public static String getProperty(String key){}
- 示例:
package top.open1024.system.demo1;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Properties;
/**
* @author open1024
* @version 1.0
* @since 2021-09-25 09:47
*/
public class Test {
public static void main(String[] args) {
// 返回当前系统时间距离1970-1-1 0:0:0的毫秒值:
long current = System.currentTimeMillis();
System.out.println("current = " + current);
// 复制数组中的元素
int[] arr = {1, 2, 3, 4, 5, 6};
int[] target = new int[arr.length];
System.arraycopy(arr, 0, target, 0, 2);
System.out.println(Arrays.toString(target));
// 获取所有系统属性
Properties properties = System.getProperties();
Enumeration<?> enumeration = properties.propertyNames();
while (enumeration.hasMoreElements()) {
Object o = enumeration.nextElement();
System.out.println("o = " + o);
}
// 获取指定系统属性
String os = System.getProperty("os.name");
System.out.println("os = " + os);
}
}
3.2 Runtime类
3.2.1 概述
-
每个应用程序都有一个Runtime类的实例,使得应用程序能够和其运行的环境相连接。
-
应用程序不能创建自己的Runtime实例,只能通过getRuntime()方法获取当前的运行时。
3.2.2 常用方法
- 返回与当前 Java 应用程序相关的运行时对象:
public static Runtime getRuntime() {}
- 返回 Java 虚拟机中的内存总量(此方法返回的值可能随时间的推移而变化,这取决于主机环境):
public native long totalMemory();
- 返回 Java 虚拟机中的空闲内存量(调用 gc 方法可能导致 freeMemory 返回值的增加):
public native long freeMemory();
- 示例:
package top.open1024.runtime.demo;
/**
* @author open1024
* @version 1.0
* @since 2021-09-25 10:29
*/
public class Test {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
Runtime runtime1 = Runtime.getRuntime();
System.out.println(runtime == runtime1); // true
long totalMemory = runtime.totalMemory();
System.out.println("totalMemory = " + totalMemory); // 512753664
long freeMemory = runtime.freeMemory();
System.out.println("freeMemory = " + freeMemory); // 504700544
}
}
4 数学相关的类
4.1 Math类
-
Math类位于java.lang包下,包含了用于执行基本数学运算的方法,如:初等指数、对数、平方根和三角函数等。类似这样的工具类,其所有的方法均为静态方法。
-
绝对值:
public static double abs(double a){}
- 返回大于等于参数的最小的整数:
public static double ceil(double a){}
- 返回小于等于参数最大的整数:
public static double floor(double a)
- 四舍五入方法 :
public static long round(double a){}
- 返回a的b幂次方法:
public static double pow(double a,double b){}
- 返回a的平方根:
public static double sqrt(double a){}
- 返回[0,1)的随机值:
public static double random(){}
- 返回圆周率:
public static final double PI
- 返回x,y中的最大值:
public static double max(double x, double y){}
- 返回x,y中的最小值:
public static double min(double x, double y){}
- 示例:
package top.open1024.math.demo1;
/**
* @author open1024
* @version 1.0
* @since 2021-09-25 10:46
*/
public class Test {
public static void main(String[] args) {
double pi = Math.PI;
System.out.println("pi = " + pi); // pi = 3.141592653589793
double e = Math.E;
System.out.println("e = " + e); // e = 2.718281828459045
int abs = Math.abs(-1);
System.out.println("abs = " + abs); // abs = 1
// 向上取整:大于或等于参数的最小整数
double ceil = Math.ceil(5.5);
System.out.println("ceil = " + ceil); // ceil = 6.0
ceil = Math.ceil(5);
System.out.println("ceil = " + ceil); // ceil = 6.0
ceil = Math.ceil(-5.5);
System.out.println("ceil = " + ceil); // ceil = -5.0
// 向下取整:小于或等于参数的最大整数
double floor = Math.floor(5.5);
System.out.println("floor = " + floor); // floor = 5.0
floor = Math.floor(5);
System.out.println("floor = " + floor); // floor = 5.0
floor = Math.floor(-5.5);
System.out.println("floor = " + floor); // floor = -6.0
// 四舍五入
long round = Math.round(5.1);
System.out.println("round = " + round); // round = 5
round = Math.round(5.65);
System.out.println("round = " + round); // round = 6
// 指数
double pow = Math.pow(2, 2);
System.out.println("pow = " + pow); // pow = 4.0
// 平方根
double sqrt = Math.sqrt(4);
System.out.println("sqrt = " + sqrt); // sqrt = 2.0
// 最大值
int max = Math.max(1, 2);
System.out.println("max = " + max); // max = 2
// 最小值
int min = Math.min(1, -2);
System.out.println("min = " + min); // min = -2
}
}
4.2 大数运算类
4.2.1 概述
-
基本数据类型long、double都有其取值范围,一般遇到超过范围的数据,就需要用来大数运算类了。
-
java.math.BigInteger:大整数。
-
java.math.BigDecimal:大浮点。
4.2.2 BigInteger
- 构造方法:
public BigInteger(String val){}
- 加法:
public BigInteger add(BigInteger val){}
- 减法:
public BigInteger subtract(BigInteger val) {}
- 乘法:
public BigInteger multiply(BigInteger val){}
- 除法:
public BigInteger divide(BigInteger val){}
- 余数:
public BigInteger remainder(BigInteger val){}
- 示例:
package top.open1024.big.demo1;
import java.math.BigInteger;
/**
* @author open1024
* @version 1.0
* @since 2021-09-26 11:00
*/
public class Test {
public static void main(String[] args) {
BigInteger b1 = new BigInteger("124");
BigInteger b2 = new BigInteger("123");
System.out.println("加法:" + b1.add(b2)); // 加法:247
System.out.println("减法:" + b1.subtract(b2)); // 减法:1
System.out.println("乘法:" + b1.multiply(b2)); // 乘法:15252
System.out.println("除法:" + b1.divide(b2)); // 除法:1
System.out.println("余数:" + b1.remainder(b2)); // 余数:1
}
}
4.2.3 RoundingMode枚举类
-
UP:远离零方向舍入的舍入模式。
-
DOWN:向零方向舍入的舍入模式。
-
CEILING:向正无限大方向舍入的舍入模式。
-
FLOOR:向负无限大方向舍入的舍入模式。
-
HALF_UP:向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向上舍入。
-
HALF_DOWN:向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向下舍入。
-
HALF_EVEN:向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。
-
UNNECESSARY:用于断言请求的操作具有精确结果的舍入模式,因此不需要舍入。
4.2.4 BigDecimal
- 构造方法:
public BigDecimal(String val) {}
- 加法:
public BigDecimal add(BigDecimal augend){}
- 减法:
public BigDecimal subtract(BigDecimal subtrahend){}
- 乘法:
public BigDecimal multiply(BigDecimal multiplicand) {}
- 除法:
public BigDecimal divide(BigDecimal divisor){}
public BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode){}
public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode){}
- 余数:
public BigDecimal remainder(BigDecimal divisor){}
- 示例:
package top.open1024.big.demo2;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* @author open1024
* @version 1.0
* @since 2021-09-26 14:16
*/
public class Test {
public static void main(String[] args) {
BigDecimal b1 = new BigDecimal("3.55");
BigDecimal b2 = new BigDecimal("2.12");
System.out.println("加法:" + b1.add(b2));
System.out.println("减法:" + b1.subtract(b2));
System.out.println("乘法:" + b1.multiply(b2));
System.out.println("除法:" + b1.divide(b2, 2, RoundingMode.HALF_UP));
}
}
5 数组的相关操作
5.1 数组的算法升华
5.1.1 数组的反转
-
所谓的数组的反转:就是一开始是[1,2,3,4,5],经过数组的反转之后变成了[5,4,3,2,1]。
-
其实,数组的反转就是对称位置的元素交换。
注意:数组的反转不是数组的倒叙遍历。
-
方法一:
-
- 借助一个新的数组。
-
- 首尾对应位置交换。
-
- 将新数组的地址赋值给旧数组。
- 示例:
package top.open1024.array.demo1;
import java.util.Arrays;
/**
* @author open1024
* @version 1.0
* @since 2021-09-25 13:02
*/
public class Test {
public static void main(String[] args) {
// 原来的数组
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8};
// 新的数组
int[] newArr = new int[arr.length];
// 给新的数组中插入值
for (int i = 0; i < newArr.length; i++) {
newArr[i] = arr[arr.length - 1 - i];
}
// 将原来的数组指向新的数组
arr = newArr;
// 打印输出
System.out.println(Arrays.toString(arr));
}
}
- 方法二:数组对称位置的元素互换。
- 示例:
package top.open1024.array.demo2;
import java.util.Arrays;
/**
* @author open1024
* @version 1.0
* @since 2021-09-25 13:08
*/
public class Test {
public static void main(String[] args) {
// 原来的数组
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8};
// 数组反转
for (int i = 0, j = arr.length - 1; i < j; i++, j--) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 打印输出
System.out.println(Arrays.toString(arr));
}
}
5.1.2 数组的二分查找法
-
数组的查找:判断一个元素是否存在于数组中。
-
数组的基本查找法:遍历数组,判断即可。
-
数组的二分查找法(折半查找法):要求数组元素必须支持比较大小,并且数组中的元素已经按大小排好序,然后对半查找。
-
二分查找法的步骤:
-
- ① 定义两个遍历,表示要查找的范围。默认min=0,max=最大索引。
-
- ② 循环查找,但是min<=max。
-
- ③ 计算出mid的值。
-
- ④ 判断mid位置的元素是否为要查找的元素,如果是,直接返回的索引。
-
- ⑤ 如果要查找的值在mid的左半边,那么min值不变,max=mid -1,继续下次循环查找。
-
- ⑥ 如果要查找的值在mid的右半边,那么max值不变,min=mid +1,继续下次循环查找。
-
- ⑦ 当min > max的时候,表示要查找的元素在数组中不存在,返回-1。
-
示例:
package top.open1024.array.demo3;
/**
* 基本查找法
*
* @author open1024
* @version 1.0
* @since 2021-09-25 13:39
*/
public class Test {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
int result = basicSearch(arr, 6);
System.out.println("result = " + result);
}
/**
*
* 数组的基本查找法
*
* @param arr 数组
* @param key 元素
* @return 如果元素在数组中,则返回元素在数组中的索引位置;否则,返回-1
*/
public static int basicSearch(int[] arr, int key) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == key) {
return i;
}
}
return -1;
}
}
- 示例:
package top.open1024.array.demo4;
/**
* @author open1024
* @version 1.0
* @since 2021-09-25 13:46
*/
public class Test {
public static void main(String[] args) {
int[] arr = {1, 5, 8, 12, 15};
int result = binarySearch(arr, 9);
System.out.println(result);
}
/**
*
* 数组的二分查找法
*
* @param arr 数组
* @param key 元素
* @return 如果元素在数组中,则返回元素在数组中的索引位置;否则,返回-1
*/
public static int binarySearch(int[] arr, int key) {
// 起始元素索引
int min = 0;
// 最后元素索引
int max = arr.length - 1;
while (min <= max) {
// 计算中间元素的索引
int mid = (min + max) / 2;
// 如果中间元素就是需要查找的元素,直接返回索引
if (key == arr[mid]) {
return mid;
}
// 如果需要查找的元素比中间的元素大,那么min就是此时的mid+1,然后再计算mid
if (key > arr[mid]) {
min = mid + 1;
}
// 如果需要查找的元素比中间的元素小,那么max就是此时的mid-1,然后再计算mid
if (key < arr[mid]) {
max = mid - 1;
}
}
return -1;
}
}
5.1.3 冒泡排序
-
排序:将一组数据按照固定的规则进行排列。
-
冒泡排序:相邻的数据两两比较,小的放在前面,大的放在后面。
注意:
-
如果有n个数据进行排序,总共需要比较n-1次。
-
每一次比较完毕,下一次的比较就会少一个数据参与。
-
示例:
package top.open1024.array.demo5;
import java.util.Arrays;
/**
* @author open1024
* @version 1.0
* @since 2021-09-25 15:14
*/
public class Test {
public static void main(String[] args) {
int[] arr = {3, 5, 2, 1, 4};
System.out.println("排序之前:" + Arrays.toString(arr));
sort(arr);
System.out.println("排序之后:" + Arrays.toString(arr));
}
/**
* 冒泡排序
*
* @param arr 需要排序的数据
*/
public static void sort(int[] arr) {
// 外层循环控制的是次数,比数组的长度少1次
for (int i = 0; i < arr.length - 1; i++) {
// 内层循环就是实际循环比较的
// -1 为了让数组不越界
// -i 每一轮结束之后,就会少比一个数字
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
}
5.1.4 递归
-
递归:以编程的角度来看,递归指的是方法定义中调用方法本身的现象。
-
递归解决问题的思路:
-
- ① 将一个复杂的问题层层转换为一个
和原问题类似的规模较小
的问题来求解。
- ① 将一个复杂的问题层层转换为一个
-
- ② 递归策略只需要
少量的程序
就可以描述出解题过程所需要的多次的重复计算。
- ② 递归策略只需要
-
递归解决问题要遵循以下的规则:
-
- ① 递归出口:否则会内存溢出。
-
- ② 递归规则:和原问题相似的规模较小的问题。
-
示例:
package top.open1024.array.demo7;
/**
* @author open1024
* @version 1.0
* @since 2021-09-25 15:57
*/
public class Test {
public static void main(String[] args) {
int sum = sum(100);
System.out.println("sum = " + sum);
}
/**
* 使用递归求和
*
* @param n 整数
* @return 和
*/
public static int sum(int n) {
if (n == 1) {
return 1;
}
return n + sum(n - 1);
}
}
- 示例:
package top.open1024.array.demo8;
/**
* 需求:用递归求5的阶乘,并将结果输出在控制台上。
* 分析:
* ① 阶乘:一个正整数的阶乘是所有小于以及等于该数的正整数的乘积,自然数n的阶乘写作n!
* ② 递归出口:1!=1
* ③ 递归规则:n!=n*(n-1)!
*
* @author open1024
* @version 1.0
* @since 2021-09-25 16:04
*/
public class Test {
public static void main(String[] args) {
int factorial = factorial(5);
System.out.println("factorial = " + factorial);
}
public static int factorial(int n) {
if (n == 1) {
return 1;
}
return n * factorial(n - 1);
}
}
5.1.5 数组的扩容
- 当原来的数组长度不够的时候需要扩容,那么新建一个数组,并指定长度,其长度为原来的1.5倍或2倍等,然后将元素复制到新数组中,并将新添加的元素放到新数组的后面。
注意:
-
新数组的长度定义多少合适,看实际情况,如果新增的元素个数确定,那么可以直接指定长度;如果新增的元素个数不确定,那么可以扩容为原来的1.5倍或2倍等。
-
数组扩容太多会造成资源浪费,太少会导致频繁扩容,效率低下。
-
示例:
package top.open1024.array.demo9;
import java.util.Arrays;
/**
* 数组扩容
*
* @author open1024
* @version 1.0
* @since 2021-09-25 16:31
*/
public class Test {
public static void main(String[] args) {
// 原数组
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8};
// 扩容的数组
int[] newArr = new int[arr.length * 2];
// 将数组的数据拷贝到新数组中
System.arraycopy(arr, 0, newArr, 0, arr.length);
// 如果还需要使用arr,可以让arr指向新数组
arr = newArr;
// 添加新数据到arr的最后
arr[8] = 10;
// 遍历显示
System.out.println(Arrays.toString(arr));
}
}
5.1.6 数组元素的插入
-
在原数组的某个index插入一个元素。
-
① 如果原数组未满,那么直接将index后面的元素(包括index上的元素)移动到后面,然后将元素插入到index上。
-
② 如果原数组已经满了,那么先扩容,然后重复①。
-
示例:原数组未满
package top.open1024.array.demo10;
import java.util.Arrays;
/**
* @author open1024
* @version 1.0
* @since 2021-09-26 08:16
*/
public class Test {
public static void main(String[] args) {
// 原数组
String[] str = new String[5];
str[0] = "张三";
str[1] = "李四";
str[2] = "王五";
// 现在想在index为1的位置上插入一个元素赵六
// 将index为1的位置以及后面的元素依次移动1位
System.arraycopy(str, 1, str, 2, 2);
// 在index为1的位置插入元素
str[1] = "赵六";
// 打印输出
System.out.println(Arrays.toString(str));
}
}
- 示例:原数组已满
package top.open1024.array.demo11;
import java.util.Arrays;
/**
* @author open1024
* @version 1.0
* @since 2021-09-26 08:22
*/
public class Test {
public static void main(String[] args) {
// 原数组
String[] str = new String[3];
str[0] = "张三";
str[1] = "李四";
str[2] = "王五";
// 现在想在index为1的位置上插入一个元素赵六
String[] dest = new String[4];
// 扩容
System.arraycopy(str, 0, dest, 0, str.length);
// str指向新数组
str = dest;
// 将index为1的位置以及后面的元素依次移动1位
System.arraycopy(str, 1, str, 2, 2);
// 在index为1的位置插入元素
str[1] = "赵六";
// 打印输出
System.out.println(Arrays.toString(str));
}
}
5.1.7 数组元素的删除
-
希望删除某个index上的元素,但是不希望数组中间空的元素,那么就将index后面的元素依次向前移动一位,最后一个元素置空即可。
-
示例:
package top.open1024.array.demo12;
import java.util.Arrays;
/**
* @author open1024
* @version 1.0
* @since 2021-09-26 08:33
*/
public class Test {
public static void main(String[] args) {
String[] arr = {"张三", "李四", "王五"};
// 希望删除index为1的元素,但是不希望index为1上为空
System.arraycopy(arr, 2, arr, 1, 1);
// 最后一个元素置空
arr[2] = null;
// 打印输出
System.out.println(Arrays.toString(arr));
}
}
5.2 数组工具类
-
java.util.Arrays数组工具类,提供了很多静态方法来对数组进行操作,而且如下的每一个方法都有重载,以下只列出int[]类型的,其他类型依次类推:
-
二分查找法:要求数组有序,在数组中查找key是否存在,如果存在返回第一次找到的下标,不存在返回负数
public static int binarySearch(int[] a, int key) {}
- 根据original原数组复制一个长度为newLength的新数组,并返回新数组:
public static int[] copyOf(int[] original, int newLength) {}
- 复制original原数组的[from,to)构成新数组,并返回新数组:
public static int[] copyOfRange(int[] original, int from, int to){}
- 比较两个数组的长度、元素是否完全相同:
public static boolean equals(int[] a, int[] a2) {}
- 用val填充整个a数组:
public static void fill(int[] a, int val) {}
- 将a数组[fromIndex,toIndex)部分填充为val :
public static void fill(int[] a, int fromIndex, int toIndex, int val){}
- 将a数组按照从小到大进行排序:
public static void sort(int[] a) {}
- 将a数组的[fromIndex, toIndex)部分按照升序排列:
public static void sort(int[] a, int fromIndex, int toIndex){}
- 把a数组的元素,拼接为一个字符串,形式为:[元素1,元素2,元素3。。。]
public static String toString(int[] a) {}
- 示例:
package top.open1024.array.demo13;
import java.util.Arrays;
import java.util.Random;
/**
* @author open1024
* @version 1.0
* @since 2021-09-26 08:41
*/
public class Test {
public static void main(String[] args) {
int[] arr = new int[5];
// 打印数组,输出地址值
System.out.println(arr); // [I@1540e19d
// 数组内容转换为字符串
System.out.println("arr数组的初始状态:" + Arrays.toString(arr)); // [0, 0, 0, 0, 0]
// 向数组中填充数据
Arrays.fill(arr, 3);
System.out.println("arr数组的现在状态:" + Arrays.toString(arr)); // [3, 3, 3, 3, 3]
// 向数组中赋值100以内的随机数
Random random = new Random();
for (int i = 0; i < arr.length; i++) {
arr[i] = random.nextInt(100);
}
System.out.println("arr数组的现在状态:" + Arrays.toString(arr)); // [3, 19, 72, 81, 66]
// 根据original原数组复制一个长度为newLength的新数组,并返回新数组
int[] arr2 = Arrays.copyOf(arr, 10);
System.out.println("新数组:" + Arrays.toString(arr2)); // [93, 62, 31, 90, 88, 0, 0, 0, 0, 0]
// 两个数组比较
System.out.println(Arrays.equals(arr, arr2)); // false
// 数组排序
Arrays.sort(arr);
System.out.println(Arrays.toString(arr)); // [17, 23, 32, 57, 98]
}
}
6 日期时间API
6.1 JDk 8之前
6.1.1 Date类(★)
-
表示当前的日期对象,精确到毫秒值。
-
构造方法:
public Date() {}
public Date(long date) {}
- 获取当前日期对应的毫秒值:
public long getTime() {}
- 将毫秒值设置为日期:
public void setTime(long time){}
- 示例:
package top.open1024.date.jdk7.demo1;
import java.util.Date;
/**
* @author open1024
* @version 1.0
* @since 2021-09-26 14:48
*/
public class Test {
public static void main(String[] args) {
Date date = new Date();
System.out.println("date = " + date); // date = Sun Sep 26 14:48:52 CST 2021
Date date1 = new Date(1632638970000L);
System.out.println("date1 = " + date1); // date1 = Sun Sep 26 14:49:30 CST 2021
long time = date.getTime();
System.out.println("time = " + time); // time = 1632639026166
date.setTime(1632638970000L);
System.out.println("date = " + date); // date = Sun Sep 26 14:49:30 CST 2021
}
}
6.1.2 Calendar
-
Calendar
类是一个抽象类,它为特定瞬间与一组诸如YEAR
、MONTH
、DAY_OF_MONTH
、HOUR
等 [日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。瞬间可用毫秒值来表示,它是距历元(即格林威治标准时间 1970 年 1 月 1 日的 00:00:00.000,格里高利历)的偏移量。Calendar
提供了一个类方法getInstance
,以获得此类型的一个通用的对象。 -
获取Calendar实例:
public static Calendar getInstance() {}
- 获取给定日历字段的值:
public int get(int field) {}
- 修改日历的值
public void set(int field, int value) {}
- 设置日历字段的偏移量:
public abstract void add(int field, int amount);
- 示例:
package top.open1024.date.jdk7.demo2;
import java.util.Calendar;
/**
* @author open1024
* @version 1.0
* @since 2021-09-26 14:55
*/
public class Test {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1;
int day = calendar.get(Calendar.DAY_OF_MONTH);
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
int milliSecond = calendar.get(Calendar.MILLISECOND);
// 2021-9-26 15:14:6:16
System.out.print(year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second + ":" + milliSecond);
}
}
- 示例:
package top.open1024.date.jdk7.demo3;
import java.util.Calendar;
/**
* @author open1024
* @version 1.0
* @since 2021-09-26 15:39
*/
public class Test {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2022);
System.out.println("calendar = " + calendar.get(Calendar.YEAR));
}
}
- 示例:
package top.open1024.date.jdk7.demo4;
import java.util.Calendar;
/**
* @author open1024
* @version 1.0
* @since 2021-09-26 15:43
*/
public class Test {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
// 日历向后,偏移180天
calendar.add(Calendar.DAY_OF_MONTH, 180);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1;
int day = calendar.get(Calendar.DAY_OF_MONTH);
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
int milliSecond = calendar.get(Calendar.MILLISECOND);
System.out.print(year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second + ":" + milliSecond);
}
}
6.1.3 TimeZone
-
TimeZone表示时区。
-
获取默认的时区:
public static TimeZone getDefault() {}
- 获取所有的时区ID:
public static synchronized String[] getAvailableIDs() {}
- 根据时区ID获取时区:
public static synchronized TimeZone getTimeZone(String ID) {}
public static TimeZone getTimeZone(ZoneId zoneId) {}
- 示例:
package top.open1024.date.jdk7.demo5;
import java.util.Arrays;
import java.util.TimeZone;
/**
* @author open1024
* @version 1.0
* @since 2021-09-26 15:46
*/
public class Test {
public static void main(String[] args) {
TimeZone aDefault = TimeZone.getDefault();
System.out.println("aDefault = " + aDefault.getID()); // Asia/Shanghai
String[] availableIDs = TimeZone.getAvailableIDs();
System.out.println("availableIDs = " + Arrays.toString(availableIDs));
TimeZone timeZone = TimeZone.getTimeZone("Asia/Shanghai");
System.out.println("timeZone = " + timeZone);
}
}
6.1.4 SimpleDateFormat
-
SimpleDateFormat:日期格式化类。
-
构造方法:
public SimpleDateFormat(String pattern) {}
- 将日期对象格式化为字符串:
public final String format(Date date) {}
- 将字符串解析为日期对象:
public Date parse(String source) throws ParseException {}
- 示例:
package top.open1024.date.jdk7.demo6;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author open1024
* @version 1.0
* @since 2021-09-26 16:00
*/
public class Test {
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date();
String format = sdf.format(date);
System.out.println("format = " + format); // format = 2021-09-26 16:02:17
Date parse = sdf.parse(format);
System.out.println("parse = " + parse); // parse = Sun Sep 26 16:02:17 CST 2021
}
}
6.2 JDK 8之后(★)
6.2.1 概述
-
Java 1.0 中包含了一个Date类,但是它的大多数方法已经在Java 1.1中引入Calendar类的时候被废弃了,而Calendar并不比Date类好多少,它们有如下的问题:
-
- ① 可变性:像日期和时间这样的类对象应该是不可变的。Calendar类可以使用三种方法更改日历字段:
set()
、add()
和roll()
。
- ① 可变性:像日期和时间这样的类对象应该是不可变的。Calendar类可以使用三种方法更改日历字段:
-
- ② 偏移性:Date中的年份是从1900年开始的,而月份是从0开始的。
-
- ③ 格式化:格式化只对Date有效,Calendar则不行。
-
- ④ 它们不是线程安全的,不能处理闰秒等。
-
可以说,对日期和时间的操作一直是Java程序员最为痛苦的地方,没有之一。第三方库joda-time在JDK8出现之前的很长时间备受Java程序员欢迎。当然,JDK8吸收了joda-time的精华,以一个新的开始为Java创建优秀的API。
-
java.time – 包含值对象的基础包
-
java.time.chrono – 提供对不同的日历系统的访问。
-
java.time.format – 格式化和解析时间和日期。
-
java.time.temporal – 包括底层框架和扩展特性。
-
java.time.zone – 包含时区支持的类。
6.2.2 本地日期时间
-
LocalDate表示本地日期,LocalTime表示本地时间,而LocalDateTIme表示本地日期时间。
-
Instant表示瞬间(本地日期时间),精确到纳秒。
LocalDateTIme和Instant的区别:
-
Instant是带时区的(以UTC为准),用来替换以前的Date。
-
LocalDateTIme是不带时区(以本地时区为准)的,用来替换以前的Calendar。
-
以LocalDateTime为例:
-
获取对象:
-
- ① 获取当前日期时间:
public static LocalDateTime now() {}
public static LocalDateTime now(ZoneId zone) {}
-
- ② 根据指定日期时间创建对象:
public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour, int minute) {}
-
获取日期时间中的每个值:
-
- 获取年份:
public int getYear() {}
-
- 获取月份(1~12):
public int getMonthValue() {}
-
- 获取月份的第几天(1~31):
public int getDayOfMonth() {}
-
- 获取一年中的第几天(1~366):
public int getDayOfYear() {}
-
- 获取星期:
public DayOfWeek getDayOfWeek() {}
-
- 获取小时:
public int getHour() {}
-
- 获取分钟:
public int getMinute() {}
-
- 获取秒:
public int getSecond() {}
-
- 获取纳秒:
public int getNano() {}
-
转换:
-
- 转换为LocalDate:
public LocalDate toLocalDate() {}
-
- 转换为LocalTime:
public LocalTime toLocalTime()
-
with系列:
-
- 修改年:
public LocalDateTime withYear(int year) {}
-
- 修改月:
public LocalDateTime withMonth(int month) {}
-
- 修改日期(一个月中的第几天):
public LocalDateTime withDayOfMonth(int dayOfMonth) {}
-
- 修改日期(一年中的第几天):
public LocalDateTime withDayOfYear(int dayOfYear) {}
-
- 修改小时:
public LocalDateTime withHour(int hour) {}
-
- 修改分钟:
public LocalDateTime withMinute(int minute) {}
-
- 修改秒:
public LocalDateTime withSecond(int second) {}
-
plus系列:如果参数为正整数,则为增加;否则,则为减少
-
- 增加年或减少年:
public LocalDateTime plusYears(long years) {}
-
- 增加或减少月:
public LocalDateTime plusMonths(long months) {}
-
- 增加或减少日:
public LocalDateTime plusDays(long days) {}
-
- 增加或减少小时:
public LocalDateTime plusHours(long hours) {}
-
- 增加或减少分钟:
public LocalDateTime plusMinutes(long minutes) {}
-
- 增加或减少秒:
public LocalDateTime plusSeconds(long seconds) {}
-
- 增加或减少周:
public LocalDateTime plusWeeks(long weeks) {}
-
minus系列:如果参数为正整数,则为减少;否则,则为增加
-
- 减少或添加年:
public LocalDateTime minusYears(long years) {}
-
- 减少或添加月:
public LocalDateTime minusMonths(long months) {}
-
- 减少或添加日:
public LocalDateTime minusDays(long days) {}
-
- 减少或添加小时:
public LocalDateTime minusHours(long hours) {}
-
- 减少或添加分钟:
public LocalDateTime minusMinutes(long minutes) {}
-
- 减少或添加秒:
public LocalDateTime minusSeconds(long seconds) {}
-
- 减少或添加周:
public LocalDateTime minusWeeks(long weeks) {}
-
比较两个时间的大小:
-
- 是否在另一个时间之前:
public boolean isBefore(ChronoLocalDateTime<?> other) {}
-
- 两个时间是否相等:
public boolean isEqual(ChronoLocalDateTime<?> other) {}
-
- 是否在另一个时间之后:
public boolean isAfter(ChronoLocalDateTime<?> other) {}
- 示例:
package top.open1024.date.jdk8.demo1;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
/**
* @author open1024
* @version 1.0
* @since 2021-09-26 19:59
*/
public class Test {
public static void main(String[] args) {
LocalDate now = LocalDate.now();
System.out.println("now = " + now); // now = 2021-09-26
LocalTime now1 = LocalTime.now();
System.out.println("now1 = " + now1); // now1 = 20:02:32.659
LocalDateTime now2 = LocalDateTime.now();
System.out.println("now2 = " + now2); // now2 = 2021-09-26T20:02:32.660
}
}
- 示例:
package top.open1024.date.jdk8.demo9;
import java.time.Instant;
import java.time.LocalDateTime;
/**
* @author open1024
* @version 1.0
* @since 2021-09-27 09:48
*/
public class Test {
public static void main(String[] args) {
Instant now = Instant.now();
System.out.println("now = " + now); // now = 2021-09-27T01:54:39.351Z
LocalDateTime now1 = LocalDateTime.now();
System.out.println("now1 = " + now1); // now1 = 2021-09-27T09:54:39.401
}
}
- 示例:
package top.open1024.date.jdk8.demo3;
import java.time.LocalDateTime;
/**
* @author open1024
* @version 1.0
* @since 2021-09-26 20:10
*/
public class Test {
public static void main(String[] args) {
LocalDateTime of = LocalDateTime.of(2021, 11, 11, 11, 11, 11);
System.out.println("of = " + of); // of = 2021-11-11T11:11:11
}
}
- 示例:
package top.open1024.date.jdk8.demo4;
import java.time.DayOfWeek;
import java.time.LocalDateTime;
/**
* @author open1024
* @version 1.0
* @since 2021-09-27 06:23
*/
public class Test {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
int year = now.getYear();
System.out.println("获取年份:" + year);
int monthValue = now.getMonthValue();
System.out.println("获取月份:" + monthValue);
int dayOfMonth = now.getDayOfMonth();
System.out.println("获取天数:" + dayOfMonth);
int dayOfYear = now.getDayOfYear();
System.out.println("获取一年中的第" + dayOfYear + "天");
DayOfWeek dayOfWeek = now.getDayOfWeek();
System.out.println("获取星期" + dayOfWeek.getValue());
int hour = now.getHour();
System.out.println("获取小时:" + hour);
int minute = now.getMinute();
System.out.println("获取分钟:" + minute);
int second = now.getSecond();
System.out.println("获取秒:" + second);
int nano = now.getNano();
System.out.println("获取纳秒:" + nano);
}
}
- 示例:
package top.open1024.date.jdk8.demo5;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
/**
* @author open1024
* @version 1.0
* @since 2021-09-27 08:17
*/
public class Test {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
// 转换为LocalDate
LocalDate localDate = now.toLocalDate();
System.out.println("localDate = " + localDate);
// 转换为LocalTime
LocalTime localTime = now.toLocalTime();
System.out.println("localTime = " + localTime);
}
}
- 示例:
package top.open1024.date.jdk8.demo9;
import java.time.LocalDateTime;
/**
* @author open1024
* @version 1.0
* @since 2021-09-27 08:35
*/
public class Test {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
System.out.println("now = " + now); // now = 2021-09-27T08:41:04.197
LocalDateTime localDateTime = now.withYear(2022);
System.out.println("修改年 = " + localDateTime); // 修改年 = 2022-09-27T08:41:04.197
LocalDateTime localDateTime1 = now.withMonth(10);
System.out.println("修改月 = " + localDateTime1); // 修改月 = 2021-10-27T08:41:04.197
LocalDateTime localDateTime2 = now.withDayOfMonth(28);
System.out.println("修改日期(一个月中的第几天) = " + localDateTime2); // 修改日期(一个月中的第几天) = 2021-09-28T08:41:04.197
LocalDateTime localDateTime3 = now.withDayOfYear(15);
System.out.println("修改日期(一年中的第几天) = " + localDateTime3); // 修改日期(一年中的第几天) = 2021-01-15T08:41:04.197
LocalDateTime localDateTime4 = now.withHour(10);
System.out.println("修改小时 = " + localDateTime4); // 修改小时 = 2021-09-27T10:41:04.197
LocalDateTime localDateTime5 = now.withMinute(15);
System.out.println("修改分钟 = " + localDateTime5); // 修改分钟 = 2021-09-27T08:15:04.197
LocalDateTime localDateTime6 = now.withSecond(10);
System.out.println("修改秒 = " + localDateTime6); // 修改秒 = 2021-09-27T08:41:10.197
}
}
- 示例:
package top.open1024.date.jdk8.demo7;
import java.time.LocalDateTime;
/**
* @author open1024
* @version 1.0
* @since 2021-09-27 09:25
*/
public class Test {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
System.out.println("now = " + now); // now = 2021-09-27T09:30:21.527
LocalDateTime localDateTime = now.plusYears(1);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 2022-09-27T09:30:21.527
LocalDateTime localDateTime1 = now.plusYears(-1);
System.out.println("localDateTime1 = " + localDateTime1); // localDateTime1 = 2020-09-27T09:30:21.527
LocalDateTime localDateTime2 = now.plusMonths(1);
System.out.println("localDateTime2 = " + localDateTime2); // localDateTime2 = 2021-10-27T09:30:21.527
LocalDateTime localDateTime3 = now.plusDays(1);
System.out.println("localDateTime3 = " + localDateTime3); // localDateTime3 = 2021-09-28T09:30:21.527
LocalDateTime localDateTime4 = now.plusHours(1);
System.out.println("localDateTime4 = " + localDateTime4); // localDateTime4 = 2021-09-27T10:30:21.527
LocalDateTime localDateTime5 = now.plusMinutes(1);
System.out.println("localDateTime5 = " + localDateTime5); // localDateTime5 = 2021-09-27T09:31:21.527
LocalDateTime localDateTime6 = now.plusSeconds(1);
System.out.println("localDateTime6 = " + localDateTime6); // localDateTime6 = 2021-09-27T09:30:22.527
LocalDateTime localDateTime7 = now.plusWeeks(1);
System.out.println("localDateTime7 = " + localDateTime7); // localDateTime7 = 2021-10-04T09:30:21.527
}
}
- 示例:
package top.open1024.date.jdk8.demo8;
import java.time.LocalDateTime;
/**
* @author open1024
* @version 1.0
* @since 2021-09-27 09:34
*/
public class Test {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
System.out.println("now = " + now); // now = 2021-09-27T09:39:01.406
LocalDateTime localDateTime = now.minusYears(1);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 2020-09-27T09:39:01.406
LocalDateTime localDateTime1 = now.minusMonths(1);
System.out.println("localDateTime1 = " + localDateTime1); // localDateTime1 = 2021-08-27T09:39:01.406
LocalDateTime localDateTime2 = now.minusDays(1);
System.out.println("localDateTime2 = " + localDateTime2); // localDateTime2 = 2021-09-26T09:39:01.406
LocalDateTime localDateTime3 = now.minusHours(1);
System.out.println("localDateTime3 = " + localDateTime3); // localDateTime3 = 2021-09-27T08:39:01.406
LocalDateTime localDateTime4 = now.minusMinutes(1);
System.out.println("localDateTime4 = " + localDateTime4); // localDateTime4 = 2021-09-27T09:38:01.406
LocalDateTime localDateTime5 = now.minusSeconds(1);
System.out.println("localDateTime5 = " + localDateTime5); // localDateTime5 = 2021-09-27T09:39:00.406
LocalDateTime localDateTime6 = now.minusWeeks(1);
System.out.println("localDateTime6 = " + localDateTime6); // localDateTime6 = 2021-09-20T09:39:01.406
}
}
- 示例:
package top.open1024.date.jdk8.demo10;
import java.time.LocalDateTime;
/**
* @author open1024
* @version 1.0
* @since 2021-09-27 09:57
*/
public class Test {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
LocalDateTime localDateTime = LocalDateTime.now().plusHours(1);
System.out.println(now.isBefore(localDateTime)); // true
System.out.println(now.isAfter(localDateTime)); // false
System.out.println(now.isEqual(localDateTime)); // false
}
}
6.2.3 指定时区日期时间ZonedDateTime
-
常见的时区:
-
- Asia/Shanghai。
-
- UTC。
-
- America/New_York。
-
示例:
package top.open1024.date.jdk8.demo13;
import java.time.ZoneId;
import java.time.ZonedDateTime;
/**
* @author open1024
* @version 1.0
* @since 2021-09-27 13:46
*/
public class Test {
public static void main(String[] args) {
ZonedDateTime now = ZonedDateTime.now();
System.out.println("now = " + now); // 2021-09-27T13:46:28.445+08:00[Asia/Shanghai]
ZonedDateTime now1 = ZonedDateTime.now(ZoneId.of("America/New_York"));
System.out.println("now1 = " + now1); // 2021-09-27T01:47:18.093-04:00[America/New_York]
}
}
6.2.4 持续日期/时间Period和Duration
-
Period:表示一段时间的区间,用来度量
年、月、日和几天
之间的时间值。 -
- 获取Period对象:
public static Period between(LocalDate startDateInclusive, LocalDate endDateExclusive) {}
-
- 获取区间相差的年份:
public int getYears() {}
-
- 获取区间相差的月份:
public int getMonths() {}
-
- 获取区间相差的天数:
public int getDays() {}
-
- 获取区间相差总的月份:
public long toTotalMonths() {}
-
Duration:表示时间的区间,用来度量
秒和纳秒
之间的时间值。 -
- 获取Duration对象:
public static Duration between(Temporal startInclusive, Temporal endExclusive) {}
-
- 获取相差的天数:
public long toDays() {}
-
- 获取相差的小时:
public long toHours() {}
-
- 获取相差的分钟:
public long toMinutes() {}
-
- 获取相差的毫秒:
public long toMillis() {}
-
- 获取相差的纳秒:
public long toNanos() {}
- 示例:
package top.open1024.date.jdk8.demo11;
import java.time.LocalDate;
import java.time.Period;
/**
* @author open1024
* @version 1.0
* @since 2021-09-27 11:23
*/
public class Test {
public static void main(String[] args) {
LocalDate now = LocalDate.now();
System.out.println("now = " + now); // now = 2021-09-27
LocalDate future = LocalDate.now().plusYears(1).plusDays(1).plusMonths(1);
System.out.println("future = " + future); // future = 2022-10-28
Period period = Period.between(now, future);
int years = period.getYears();
System.out.println("区间相差的年 = " + years); // 区间相差的年 = 1,其实就是 future 的year - now的year
int months = period.getMonths();
System.out.println("区间相差的月 = " + months); // 区间相差的月 = 1,其实就是 future 的month - now的month
int days = period.getDays();
System.out.println("区间相差的天 = " + days); // 区间相差的天 = 1,其实就是 future 的day - now的day
long totalMonths = period.toTotalMonths();
System.out.println("区间相差几个月 = " + totalMonths); // 区间相差几个月 = 13,实际相差的月
}
}
- 示例:
package top.open1024.date.jdk8.demo12;
import java.time.Duration;
import java.time.LocalDateTime;
/**
* @author open1024
* @version 1.0
* @since 2021-09-27 13:26
*/
public class Test {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
System.out.println("now = " + now); // now = 2021-09-27T13:29:56.105
LocalDateTime feture = LocalDateTime.now().plusYears(1).plusMonths(1).plusDays(1).plusHours(1).plusMonths(1)
.plusSeconds(1).plusNanos(1);
System.out.println("feture = " + feture); // feture = 2022-11-28T14:29:57.106000001
Duration duration = Duration.between(now, feture);
long seconds = duration.getSeconds();
System.out.println("seconds = " + seconds); // seconds = 36896401
int nano = duration.getNano();
System.out.println("nano = " + nano); // nano = 1000001
}
}
6.2.5 日期时间格式化DateTimeFormat
-
在JDK8中,使用DateTimeFormat类进行日期时间的格式化。
-
获取DateTimeFormat:
public static DateTimeFormatter ofPattern(String pattern) {}
- 格式化:
public String format(TemporalAccessor temporal) {}
- 解析:
public TemporalAccessor parse(CharSequence text) {}
- 示例:
package top.open1024.date.jdk8.demo14;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
/**
* @author open1024
* @version 1.0
* @since 2021-09-27 13:51
*/
public class Test {
public static void main(String[] args) {
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String format = df.format(LocalDateTime.now());
System.out.println("format = " + format); // format = 2021-09-27 13:55:51
TemporalAccessor parse = df.parse("2011-11-11 11:11:11");
LocalDateTime from = LocalDateTime.from(parse);
System.out.println("from = " + from); // from = 2011-11-11T11:11:11
}
}
评论区