[英]Java String.join but also add delimiter to the end
我有数组["a", "b", "c"]
并且我想将它们连接在一起形成“a#b#c#”。 String.join 只会让我“a#b#c”。 我不能只做str += "#"
,因为这很慢(Java 必须创建一个新字符串才能做到这一点)。 因此,我必须使用StringBuilder
重写整个过程。 Java 是否有一些方法基本上是 String.join,但还将分隔符附加到末尾?
对于更多的上下文,我正在尝试使用一组字符串创建一个后缀数组数据结构,因此这部分实际上是一个瓶颈。
您可以使用 Stream API Collectors.joining() 有这样的前缀和后缀参数:
Stream.of("a", "b", "c")
.collect(Collectors.joining("#", "", "#"));
其中加入参数分别是定界符、前缀、后缀。
此外,您可以像上面评论中的@Wander Nauta 所说的那样,将一个空字符串添加到您的数组中
我已经启动了 JMH,并重现了如下写的性能差异:
public class Benchmarks {
private static final String[] arr = {"a", "b", "c"};
@Benchmark
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(value = 1, warmups = 1)
@BenchmarkMode(Mode.AverageTime)
public String joinAndConcat() {
return String.join("#", arr) + "#";
}
@Benchmark
@Fork(value = 1, warmups = 1)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@BenchmarkMode(Mode.AverageTime)
public String streamsJoining() {
return Stream.of(arr)
.parallel()
.collect(Collectors.joining("#", "", "#"));
}
@Benchmark
@Fork(value = 1, warmups = 1)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@BenchmarkMode(Mode.AverageTime)
public String stringJoiner() {
StringJoiner joiner = new StringJoiner("#", "", "#");
for (String el : arr) {
joiner.add(el);
}
return joiner.toString();
}
}
结果:
> Benchmark Mode Cnt Score Error Units
> Benchmarks.joinAndConcat avgt 5 46,670 ± 0,139 ns/op
> Benchmarks.streamsJoining avgt 5 73,336 ± 0,180 ns/op
> Benchmarks.stringJoiner avgt 5 27,236 ± 0,386 ns/op
但是您必须明白,对于大多数应用程序来说,46 nSec
只是一个很小的差异。
以下是使用JMH的性能指标:
Benchmark Mode Cnt Score Error Units
StringJoiner thrpt 100 23641181.522 ± 237176.955 ops/s
JoinAndConcat thrpt 100 14197523.377 ± 130873.538 ops/s
StreamsJoining thrpt 100 9538282.522 ± 156729.920 ops/s
与使用StringJoiner
的解决方案相比,使用流的解决方案需要大约2.5 倍的时间。 在中场正如预期的那样连接连接(见问题)。 然而,我们在这里谈论的是纳秒。
显示重新计算值的性能的图形概览 ( ops/s => ns/op
):
# JMH version: 1.32
# VM version: JDK 11.0.11, OpenJDK 64-Bit Server VM, 11.0.11+9
# VM invoker: /Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home/bin/java
# VM options: <none>
# Blackhole mode: full + dont-inline hint
# Warmup: 10 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
import java.util.StringJoiner;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.openjdk.jmh.annotations.Benchmark;
public class Benchmarks {
private static final String[] arr = {"a", "b", "c"};
@Benchmark
public String joinAndConcat() {
return String.join("#", arr) + "#";
}
@Benchmark
public String streamsJoining() {
return Stream.of(arr)
.collect(Collectors.joining("#", "", "#"));
}
@Benchmark
public String stringJoiner() {
StringJoiner joiner = new StringJoiner("#", "", "#");
for (String el : arr) {
joiner.add(el);
}
return joiner.toString();
}
}
String.join()
在幕后使用StringJoiner
,因此您可以创建一个并在构造函数中将suffix
参数指定为#
:
String[] array = { "a", "b", "c" };
StringJoiner joiner = new StringJoiner("#", "", "#");
for (String el : array) {
joiner.add(el);
}
System.out.println(joiner.toString()); // a#b#c#
然而,这感觉就像微优化。 除非您的加入代码很重要,否则编写起来更具可读性:
String[] array = { "a", "b", "c" };
System.out.println(String.join("#", array) + "#"); // a#b#c#
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.