在高版本的 Java
中,字符串操作新增了如下方法:
Java 版本 |
方法名 |
方法描述 |
9 |
chars() |
返回字符串的字符值流 |
9 |
codePoints() |
返回字符串的 Unicode 值流 |
11 |
strip() |
移除首尾空白字符(支持所有 Unicode 字符) |
11 |
stripLeading() |
移除头部空白字符 |
11 |
stripTrailing() |
移除尾部空白字符 |
11 |
isBlank() |
检查字符串是否只包含空白字符 |
11 |
repeat(int count) |
返回一个由原始字符串重复 count 次组成的新字符串 |
11 |
lines() |
使用换行符将字符串拆分为一个流 |
12 |
indent(int n) |
根据参数 n 的值调整字符串的缩进 |
12 |
transform(Function<? super String, ? extends R> f) |
使用给定的函数 f 对字符串进行转换 |
12 |
describeConstable |
创建并返回一个实例本身的 Optional 对象 |
15 |
formatted(Object... args) |
使用提供的参数替换占位符,并返回一个格式化的字符串 |
15 |
stripIndent() |
移除首尾空白字符(包含换行符前后的) |
15 |
translateEscapes() |
将字符串中的转义序列转换为对应的字符 |
在 Java 9
中的 String
类新增了 chars
和 codePoints
方法,用于获取字符的 IntStream
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// 测试内容
String testContent = "中-E-\uD835\uDD0A";
// 测试 chars
System.out.println();
System.out.println("chars:");
IntStream intStreamChars = testContent.chars();
intStreamChars.forEach(e -> System.out.print(e + "=" + (char) e + " "));
// 测试 codePoints
System.out.println();
System.out.println("codePoints:");
IntStream intStreamCodePoints = testContent.codePoints();
intStreamCodePoints.forEach(e -> System.out.print(e + "=" + (char) e + " "));
|
两者都是获取字符串中的字符 ASCII
码的 IntStream
流,但 codePoints
方法可以处理 Unicode
特殊字符,输出结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
// 测试内容
String testContent = "\u2000中-E-\uD835\uDD0A-\u2000 ";
// 移除首尾空白字符(仅限 ASCII 字符)
System.out.println("text.trim():" + testContent.trim());
// Java 11 新增 - 移除首尾空白字符(支持所有 Unicode 字符)
System.out.println("text.strip():" + testContent.strip());
// Java 11 新增 - 移除头部空白字符
System.out.println("text.stripLeading():" + testContent.stripLeading());
// Java 11 新增 - 移除尾部空白字符
System.out.println("text.stripTrailing():" + testContent.stripTrailing());
// Java 15 新增 - 移除首尾空白字符(包含换行符前后的)
testContent = " \u2000中-E-回车: \n :回车 \u2000 ";
System.out.println("text.stripIndent():" + testContent.stripIndent());
|
输出结果:
仔细看这里的 trim
和 strip
方法:
trim
方法仅限 ASCII
编码的空白字符,strip
可以移除所有 Unicode
编码的空白字符。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// 测试内容
String testContent = " ";
// Java 6 新增 - 判断是否为空白字符
// 输出:false
System.out.println(testContent.isEmpty());
// Java 11 新增 - 判断是否为空白字符
// 输出:true
System.out.println(testContent.isBlank());
// 空指针异常处理
// 输出:Cannot invoke "String.isBlank()" because "testContent2" is null
String testContent2 = null;
System.out.println(testContent2.isBlank());
|
isEmpty
和 isBlank
方法最大的区别就是对空白字符串的判断,如果字符串仅仅包含空白字符,isEmpty
为真,isBlank
为假。
如果字符串为 null
,使用这两个方法都会抛出空指针异常。
在 Java 11
中新添加重复拼接字符串 repeat
方法,比如下面示例:
1
2
|
String testContent = "hello~ ";
System.out.println(testContent.repeat(3));
|
输出结果:
其底层调用了 System.arraycopy
方法进行字节拷贝,最后再封装成一个新的字符串。
Java 11
新增方法。根据字符串的换行符,将每个字符形成一个 Stream
流:
1
2
3
4
5
6
|
// 测试内容
String testContent = "hello\njava\nC++\nPHP\nGO\n";
// 返回 Stream 流的数量
System.out.println("数量:" + testContent.lines().count());
// 遍历 Stream 流输出
testContent.lines().forEach(System.out::println);
|
输出结果:
indent
是 Java 12
新增方法,用于对字符串进行缩进:
1
2
|
String testContent = "hello\njava\nC++\nPHP\nGO\n";
System.out.println(testContent.indent(3));
|
输出结果:
来看它的源码:
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
|
/**
* 缩进字符串
* @param n 缩进的空格数
* @return 缩进后的字符串
*/
public String indent(int n) {
// 如果字符串为空,则直接返回空字符串
if (isEmpty()) {
return "";
}
// 获取每一行字符串
Stream<String> stream = lines();
// 如果缩进数大于 0
if (n > 0) {
// 生成包含 n 个空格的字符串
final String spaces = " ".repeat(n);
// 对每一行字符串进行处理,将其前面添加 n 个空格
stream = stream.map(s -> spaces + s);
} else if (n == Integer.MIN_VALUE) {
// 对每一行字符串进行处理,去除开头的空格
stream = stream.map(s -> s.stripLeading());
} else if (n < 0) {
// 对每一行字符串进行处理,截取从开头到第一个非空格字符之间的子字符串
stream = stream.map(s -> s.substring(Math.min(-n, s.indexOfNonWhitespace())));
}
// 将每一行字符串通过换行符连接起来,并返回结果
return stream.collect(Collectors.joining("\n", "", "\n"));
}
|
其实就是调用了上面的 lines
方法根据根据换行符来创建一个 Stream
,然后再往前拼接指定数量的空格,最后形成新的字符串。
transform
是 Java 12
新增的方法,用于字符串转换:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// 测试内容
String testContent = " 自本非美玉,故不敢加以刻苦雕琢 ";
/*
* 对测试内容进行处理:
* 1. 移除首尾空白字符(strip 方法)
* 2. 转换为大写(toUpperCase 方法)
* 3. 将处理后的字符串拼接为 "我深怕" 开头的新字符串
*/
String result = testContent.transform(String::strip)
.transform(String::toUpperCase)
.transform(e -> "我深怕" + e);
System.out.println(result);
|
这里先用 strip
移除前后的空白字符,然后转换为大写,最后再拼接一个前缀。
结果输出:
Java 12
中的 String
实现了 Constable
接口:
1
2
3
4
5
6
7
8
9
|
public interface Constable {
/*
* 如果可以构建该实例的名义描述符,则返回一个包含它的 {@link Optional} 对象
* 若无法构建,则返回一个空的 {@link Optional} 对象。
*
* @return 包含生成的名义描述符的 {@link Optional} 对象,如果无法构建则返回一个空的 {@link Optional} 对象。
*/
Optional<? extends ConstantDesc> describeConstable();
}
|
实现源码如下所示:
1
2
3
4
5
6
7
8
9
|
/*
* 返回一个包含当前对象的 {@link Optional} 对象。
*
* @return 包含当前对象的 {@link Optional} 对象。
*/
@Override
public Optional<String> describeConstable() {
return Optional.of(this);
}
|
其实就是把字符串本身封装一个 Optional
对象返回。
示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// 测试内容
String testContent = "却又半信自己是块美玉,故又不肯庸庸碌碌,与瓦砾为伍";
Optional<String> nameOptional = testContent.describeConstable();
// 直接 get 会提示如下信息:
// 'Optional.get()' without 'isPresent()' check
System.out.println(nameOptional.get());
// 此处相当于:
// 1. 使用 'isPresent()' 方法检查 Optional 是否包含值
// 2. 打印 Optional 中的值
// if (nameOptional.isPresent()) {
// System.out.println(nameOptional.get());
// }
nameOptional.ifPresent(System.out::println);
|
输出结果:
却又半信自己是块美玉,故又不肯庸庸碌碌,与瓦砾为伍
Optional
是 Java 8
中的新特性,可用来替代对象的 != null
判断。
Java 15
中的 String
类引入了一个 formatted()
格式化新方法,它是 String.format()
方法的简写版本,它可以方便地对字符串进行格式化。
1
2
3
4
5
6
|
String testContent1 = "Hello, %s".formatted("Linux do!");
System.out.println(testContent1);
// 白白白是一只雪白的猫猫
String testContent2 = "我叫 %s,我今年已经 %d 岁啦~".formatted("白白白", 3);
System.out.println(testContent2);
|
输出结果:
在 Java 15
中,String
类引入了 translateEscapes()
新方法,用于将字符串中的转义序列转化为相应的字符。
来看下面的示例代码:
1
2
3
4
5
6
7
8
|
String testContent = "Hello\n\\n白白白\\t!";
System.out.println("===testContent===");
System.out.println(testContent);
System.out.println();
System.out.println("===translateEscapes===");
System.out.println(testContent.translateEscapes());
|
输出结果:
通过前面输出对比可以看出,正常的转义字符 \\n
经过转换一次之后变成了 \n
就不能再转换了,而新出的 translateEscapes
方法可以继续转换出转义之后的转义字符,把所有转义字符转换为真正的字符。
支持的转义字符如下:
转义序列 |
对应的字符 |
\b |
退格符 (Backspace) |
\t |
制表符 (Tab) |
\n |
换行符 (Newline) |
\f |
换页符 (Form feed) |
\r |
回车符 (Carriage return) |
\" |
双引号 (Double quote) |
\' |
单引号 (Single quote) |
\\ |
反斜线 (Backslash) |
\0 to \377 |
八进制表示的 Unicode 字符 |
\s |
空格符 (Space) |