首页 > 解决方案 > Java String.join 但还在末尾添加分隔符

问题描述

我有数组["a", "b", "c"],我想将它们连接在一起形成“a#b#c#”。String.join 只会让我得到“a#b#c”。我不能这样做str += "#",因为这很慢(Java 必须创建一个新字符串才能做到这一点)。因此,我必须使用StringBuilder. 是否有一些 Java 有基本上是 String.join 但也将分隔符附加到末尾的方法?

对于更多的上下文,我正在尝试使用一组字符串创建一个 Suffix Array 数据结构,因此这部分实际上是一个瓶颈。

标签: javastring

解决方案


您可以使用 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

但是您必须了解,nSec对于大多数应用程序来说,46 是一个非常小的差异。


推荐阅读