簡體   English   中英

Java String.join 還要在末尾添加分隔符

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM