7.2 String存储结构和API变更
这是JDK9的新特性。
产生背景:
Motivation
The current implementation of the String class stores characters in a char array, using two bytes (sixteen bits) for each character. Data gathered from many different applications indicates that strings are a major component of heap usage and, moreover, that most String objects contain only Latin-1 characters. Such characters require only one byte of storage, hence half of the space in the internal char arrays of such String objects is going unused.
使用说明:
Description
We propose to change the internal representation of the String class from a UTF-16 char array to a byte array plus an encoding-flag field. The new String class will store characters encoded either as ISO-8859-1/Latin-1 (one byte per character), or as UTF-16 (two bytes per character), based upon the contents of the string. The encoding flag will indicate which encoding is used.
结论:String 再也不用 char[] 来存储啦,改成了 byte[] 加上编码标记,节约了一些空间。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
@Stable
private final byte[] value;
...
}
拓展:StringBuffer 与 StringBuilder
那StringBuffer 和 StringBuilder 是否仍无动于衷呢?
String-related classes such as AbstractStringBuilder, StringBuilder, and StringBuffer will be updated to use the same representation, as will the HotSpot VM's intrinsic string operations.
JDK11新特性:新增了一系列字符串处理方法
描述 | 举例 |
判断字符串是否为空白 | " ".isBlank(); // true |
去除首尾空白 | " Javastack ".strip(); // "Javastack" |
去除尾部空格 | " Javastack ".stripTrailing(); // " Javastack" |
去除首部空格 | " Javastack ".stripLeading(); // "Javastack " |
复制字符串 | "Java".repeat(3);// "JavaJavaJava" |
行数统计 | "A\nB\nC".lines().count(); // 3 |
JDK12新特性:String 实现了 Constable 接口
String源码:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence,Constable, ConstantDesc {
java.lang.constant.Constable接口定义了抽象方法:
public interface Constable {
Optional<? extends ConstantDesc> describeConstable();
}
Java 12 String 的实现源码:
/**
* Returns an {@link Optional} containing the nominal descriptor for this
* instance, which is the instance itself.
*
* @return an {@link Optional} describing the {@linkplain String} instance
* @since 12
*/
@Override
public Optional<String> describeConstable() {
return Optional.of(this);
}
很简单,其实就是调用 Optional.of 方法返回一个 Optional 类型。
举例:
private static void testDescribeConstable() {
String name = "尚硅谷Java高级工程师";
Optional<String> optional = name.describeConstable();
System.out.println(optional.get());
}
结果输出:
尚硅谷Java高级工程师
JDK12新特性:String新增方法
String的transform(Function)
var result = "foo".transform(input -> input + " bar");
System.out.println(result); //foo bar
或者
var result = "foo".transform(input -> input + " bar").transform(String::toUpperCase)
System.out.println(result); //FOO BAR
对应的源码:
/**
* This method allows the application of a function to {@code this}
* string. The function should expect a single String argument
* and produce an {@code R} result.
* @since 12
*/
public <R> R transform(Function<? super String, ? extends R> f) {
return f.apply(this);
}
在某种情况下,该方法应该被称为map()。
举例:
private static void testTransform() {
System.out.println("======test java 12 transform======");
List<String> list1 = List.of("Java", " Python", " C++ ");
List<String> list2 = new ArrayList<>();
list1.forEach(element -> list2.add(element.transform(String::strip)
.transform(String::toUpperCase)
.transform((e) -> "Hi," + e))
);
list2.forEach(System.out::println);
}
结果输出:
======test java 12 transform======
Hi,JAVA
Hi,PYTHON
Hi,C++
如果使用Java 8的Stream特性,可以如下实现:
private static void testTransform1() {
System.out.println("======test before java 12 ======");
List<String> list1 = List.of("Java ", " Python", " C++ ");
Stream<String> stringStream = list1.stream().map(element -> element.strip()).map(String::toUpperCase).map(element -> "Hello," + element);
List<String> list2 = stringStream.collect(Collectors.toList());
list2.forEach(System.out::println);
}