首页 > 解决方案 > Collectors.joining 与 StringBuilder.append

问题描述

哪一个在性能方面更好?

finalWords.stream().forEach(word -> stringBuilder.append(word).append(”,“)); 
String finalResult = stringBuilder.toString();

VS

String finalResult = finalWords.stream().collect(Collectors.joining(","));

标签: javajava-8java-stream

解决方案


因为我很好奇,所以我整理了一个小基准来测试它。List它用size随机生成的小写s初始化Strings,每个小写字母的长度为10

@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Fork(3)
public class MyBenchmark {

    @Param({"10", "100", "1000", "10000", "100000"})
    private int size;

    private List<String> finalWords;

    @Setup(Level.Invocation)
    public void initialize() {
        finalWords = IntStream.range(0, size)
                              .mapToObj(i -> {
                                  return ThreadLocalRandom.current()
                                                          .ints(10, 'a', 'z' + 1)
                                                          .mapToObj(c -> Character.toString((char) c))
                                                          .collect(Collectors.joining());
                              }).collect(Collectors.toList());
    }

    public static void main(String[] args) throws Exception {
        org.openjdk.jmh.Main.main(args);
    }

    @Benchmark
    public String stringBuilder() {
        StringBuilder sb = new StringBuilder();
        finalWords.forEach(word -> sb.append(word).append(","));
        return sb.toString();
    }

    @Benchmark
    public String stream() {
        return finalWords.stream().collect(Collectors.joining(","));
    }
}

结果如下:

Benchmark                  (size)  Mode  Cnt        Score        Error  Units
MyBenchmark.stream             10  avgt   30      242.330 ±      5.177  ns/op
MyBenchmark.stream            100  avgt   30     1426.333 ±     20.183  ns/op
MyBenchmark.stream           1000  avgt   30    30779.509 ±   1114.992  ns/op
MyBenchmark.stream          10000  avgt   30   720944.424 ±  27845.997  ns/op
MyBenchmark.stream         100000  avgt   30  7701294.456 ± 648084.759  ns/op
MyBenchmark.stringBuilder      10  avgt   30      170.566 ±      1.833  ns/op
MyBenchmark.stringBuilder     100  avgt   30     1166.153 ±     21.162  ns/op
MyBenchmark.stringBuilder    1000  avgt   30    32374.567 ±    979.288  ns/op
MyBenchmark.stringBuilder   10000  avgt   30   473022.229 ±   8982.260  ns/op
MyBenchmark.stringBuilder  100000  avgt   30  4524267.849 ± 242801.008  ns/op

如您所见,StringBuilder在这种情况下,该方法更快,即使我没有指定初始容量。


推荐阅读