在Java 9中串联字符串


您是否曾经需要用Java中的列表或数组构建用逗号分隔的值列表,还是想使用串联的文件夹名称和文件路径定界符来创建文件路径?那么,在文章中Cocatenating字符串在Java中8,我已经描述了使用Java API的8做工作一个方便易方式。

这不仅减少了开发时间并避免了其他错误,而且还使您可以编写更具可读性和可理解性的代码。但是自从Java 9发行以来,到底发生了什么,它是否适用于上述文章中介绍的案例中提供的代码。

当您使用Java实现第一个应用程序或阅读一些Java书籍和文章时,您可能会注意到不应将String与+ 运算符连接在一起。如果在应用程序逻辑中串联String,那是正确的。

String是不可变的,每个String串联的结果都存储在一个新的String对象中。这需要额外的内存并减慢您的应用程序的速度,尤其是当您在循环中串联多个String时。经验丰富的Java程序员知道,使用StringBuffer类附加字符串值是首选方法,从JDK 5版本开始,该类已经被补充了一个等效的类,该类设计用于单个线程,称为StringBuilder。通常应优先于StringBuffer使用StringBuilder,因为它支持所有相同的操作,但它更快,因为它不执行同步。

现在,让我们重温上一篇文章中的示例:

String baseDirectory = "baseDir";
String subFolder = "subFolder";
String fileName = "fileName";
List<String> filePathParts = Arrays.asList(baseDirectory, subFolder, fileName);
File file = new File(String.join(File.separator, filePathParts));

调用String的join方法时,它将调用委派给稍微复杂一些的类StringJoiner,该类实际上提供的不仅仅是将字符串与参数化的定界符进行连接。如Javadoc所述:

StringJoiner用于构造 由定界符分隔的字符序列,并可选地以提供的前缀开头和以提供的后缀结尾。

在Java 8中,StringJoiner实现针对String的连接进行了优化,并且基于StringBuilder的用法。通过使用Java API来构建逗号分隔的值,我们可以确保我们的代码针对具有许多必须串联在String值上的值的用例进行了优化。StringJoiner在Java Collectors API for Streams中的集成对我们也是一个巨大的好处。但是从那时起,Java 9改变了局面。

在Java 9中,每个String 串联都转换为对invokedynamic的调用,如JDK增强建议280中所述。JEP 280更改了javac生成的静态String-concatenation字节码序列,以使用对JDK库函数的invokedynamic调用。这使得将来可以优化String串联,而无需进一步更改Java发出的字节码。

通常,这意味着与使用StringBuilder相比,使用+运算符连接String值的速度更快 ,后者在应用简单+串联优化时早先在Java 8字节码中使用。

但是,基于StringJoiner和Collectors进行字符串连接的情况下,我们已经编写的遗留代码会发生以下情况:

String suffix  = new SimpleDateFormat("yyyyMMdd").format(new Date());
String paramValue = "P";
List<String> filePathParts = Arrays.asList(baseDirectory, subFolder, "%s", fileName);
String filePath = filePathParts.stream().map(value -> String.format(value, paramValue))
          .collect(Collectors.joining(File.separator, "", suffix));
>>Output: baseDir\subFolder\P\fileName20170804

好吧,自Java 9以来,StringJoiner类也已更改,不再使用StringBuilder。而不是将值存储在StringBuilder中,而是使用String值数组,并且串联基于String提供的getChars方法:

getCharsint  srcBeginint  srcEndchar  dst []int  dstBegin

此更改只是一个实现细节,与Java 9 String串联更改没有直接关系。实际上,对于具有数百万个元素的庞大列表,新版本的性能更好,因为它不依赖于Java类(StringBuilder),而是依赖于String类实现中调用的本机方法。

好消息是,用于构建用逗号分隔的值的Java API仍然有效,并且自Java 9开始就得到了改进。更重要的是,可以依靠Java API而不是使用自定义实现或外部库,因为这是因为移到了更新的Java版本可能会优化您的旧代码,而无需重写,部署和发布旧代码的任何新版本。


原文链接:codingdict.com