千家信息网

Java代码中字符串拼接方式有哪些

发表于:2025-01-19 作者:千家信息网编辑
千家信息网最后更新 2025年01月19日,这篇文章主要为大家展示了"Java代码中字符串拼接方式有哪些",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Java代码中字符串拼接方式有哪些"这篇文章吧。
千家信息网最后更新 2025年01月19日Java代码中字符串拼接方式有哪些

这篇文章主要为大家展示了"Java代码中字符串拼接方式有哪些",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Java代码中字符串拼接方式有哪些"这篇文章吧。

分析过程

环境

  • 系统: windows 10 21H1

  • JDK: OpenJDK 1.8.0_302

分析用示例代码:

@Slf4jpublic class StringConcat {    @SneakyThrows    public static void main(String[] args) {        log.info("java虚拟机预热开始");        String[] strs = new String[6000000];        for (int i = 0; i < strs.length; i++) {            strs[i] = id();        }        loopStringJoiner(strs);        loopStringJoin(strs);        loopStringBuilder(strs);        log.info("java虚拟机预热结束");        Thread.sleep(1000);        log.info("开始测试:");        Thread.sleep(1000);        Stopwatch stopwatchLoopPlus = Stopwatch.createStarted();//        loopPlus(strs);        log.info("loop-plus: " + stopwatchLoopPlus.elapsed(TimeUnit.MILLISECONDS));        Thread.sleep(1000);        Stopwatch stopwatchLoopStringBuilderCapacity = Stopwatch.createStarted();        loopStringBuilderCapacity(strs);        log.info("loop-stringBuilderCapacity: " + stopwatchLoopStringBuilderCapacity.elapsed(TimeUnit.MILLISECONDS));        Thread.sleep(1000);        Stopwatch stopwatchLoopStringBuilder = Stopwatch.createStarted();        loopStringBuilder(strs);        log.info("loop-stringBuilder: " + stopwatchLoopStringBuilder.elapsed(TimeUnit.MILLISECONDS));        Thread.sleep(1000);        Stopwatch stopwatchLoopJoin = Stopwatch.createStarted();        loopStringJoin(strs);        log.info("loop-String.join: " + stopwatchLoopJoin.elapsed(TimeUnit.MILLISECONDS));        Thread.sleep(1000);        Stopwatch stopwatchLoopStringJoiner = Stopwatch.createStarted();        loopStringJoiner(strs);        log.info("loop-stringJoiner: " + stopwatchLoopStringJoiner.elapsed(TimeUnit.MILLISECONDS));        Thread.sleep(1000);        Stopwatch stopwatchSimplePlus = Stopwatch.createStarted();        for (int i = 0; i < 500000; i++) {            simplePlus(id(), id(), id());        }        log.info("simple-Plus: " + stopwatchSimplePlus.elapsed(TimeUnit.MILLISECONDS));        Thread.sleep(1000);        Stopwatch stopwatchSimpleStringBuilder = Stopwatch.createStarted();        for (int i = 0; i < 500000; i++) {            simpleStringBuilder(id(), id(), id());        }        log.info("simple-StringBuilder: " + stopwatchSimpleStringBuilder.elapsed(TimeUnit.MILLISECONDS));        Thread.sleep(1000);        Stopwatch stopwatchSimpleStringBuffer = Stopwatch.createStarted();        for (int i = 0; i < 500000; i++) {            simpleStringBuffer(id(), id(), id());        }        log.info("simple-StringBuffer: " + stopwatchSimpleStringBuffer.elapsed(TimeUnit.MILLISECONDS));    }    private static String loopPlus(String[] strs) {        String str = "";        for (String s : strs) {            str = str + "+" + s;        }        return str;    }    private static String loopStringBuilder(String[] strs) {        StringBuilder str = new StringBuilder();        for (String s : strs) {            str.append("+");            str.append(s);        }        return str.toString();    }    private static String loopStringBuilderCapacity(String[] strs) {        StringBuilder str = new StringBuilder(strs[0].length() * strs.length);        for (String s : strs) {            str.append("+");            str.append(s);        }        return str.toString();    }    private static String loopStringJoin(String[] strs) {        StringJoiner joiner = new StringJoiner("+");        for (String str : strs) {            joiner.add(str);        }        return joiner.toString();    }    private static String loopStringJoiner(String[] strs) {        return String.join("+", strs);    }    private static String simplePlus(String a, String b, String c) {        return a + "+" + b + "+" + c;    }    private static String simpleStringBuilder(String a, String b, String c) {        StringBuilder builder = new StringBuilder();        builder.append(a);        builder.append("+");        builder.append(b);        builder.append("+");        builder.append(c);        return builder.toString();    }    private static String simpleStringBuffer(String a, String b, String c) {        StringBuffer buffer = new StringBuffer();        buffer.append(a);        buffer.append("+");        buffer.append(b);        buffer.append("+");        buffer.append(c);        return buffer.toString();    }    private static String id() {        return UUID.randomUUID().toString();    }}

结果及总结

- java虚拟机预热开始
- java虚拟机预热结束
- 开始测试:
- loop-plus: 执行超时
- loop-stringBuilderCapacity: 285
- loop-stringBuilder: 1968
- loop-String.join: 1313
- loop-stringJoiner: 1238
- simple-Plus: 812
- simple-StringBuilder: 840
- simple-StringBuffer: 857

  • 多次测试,可发现在字符串循环拼接场景下,直接使用"+"号性能最低,有初始容量的StringBuilder性能最高,其他方式性能均没有太大差异。

  • 多次测试,可发现在字符串简单拼接场景下,使用"+"号、StringBuilder、StringBuffer性能差距在5%左右,可理解为测试误差,可认为三种方式性能一致。

代码及结果分析

1. StringBuilder与StringBuffer对比

在无争抢共享资源的场景下,JVM会使用偏向锁等方法优化,甚至会进行锁消除,使用Synchronized关键词与否,性能并无明显差异。

2. 字节码分析

对比上述#simplePlus和#simpleStringBuilder两个方法的字节码,可明显看到两方法执行内容基本一致,但是直接使用"+"号时处理流程更短,可见编译器进行了深度优化,使用优化后的字节码理论上会有更高的性能:

  // access flags 0xA  private static simplePlus(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;    // parameter  a    // parameter  b    // parameter  c   L0    LINENUMBER 125 L0    NEW java/lang/StringBuilder    DUP    INVOKESPECIAL java/lang/StringBuilder. ()V    ALOAD 0    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    LDC "+"    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    ALOAD 1    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    LDC "+"    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    ALOAD 2    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;    ARETURN   L1    LOCALVARIABLE a Ljava/lang/String; L0 L1 0    LOCALVARIABLE b Ljava/lang/String; L0 L1 1    LOCALVARIABLE c Ljava/lang/String; L0 L1 2    MAXSTACK = 2    MAXLOCALS = 3  // access flags 0xA  private static simpleStringBuilder(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;    // parameter  a    // parameter  b    // parameter  c   L0    LINENUMBER 129 L0    NEW java/lang/StringBuilder    DUP    INVOKESPECIAL java/lang/StringBuilder. ()V    ASTORE 3   L1    LINENUMBER 130 L1    ALOAD 3    ALOAD 0    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    POP   L2    LINENUMBER 131 L2    ALOAD 3    LDC "+"    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    POP   L3    LINENUMBER 132 L3    ALOAD 3    ALOAD 1    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    POP   L4    LINENUMBER 133 L4    ALOAD 3    LDC "+"    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    POP   L5    LINENUMBER 134 L5    ALOAD 3    ALOAD 2    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;    POP   L6    LINENUMBER 135 L6    ALOAD 3    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;    ARETURN   L7    LOCALVARIABLE a Ljava/lang/String; L0 L7 0    LOCALVARIABLE b Ljava/lang/String; L0 L7 1    LOCALVARIABLE c Ljava/lang/String; L0 L7 2    LOCALVARIABLE builder Ljava/lang/StringBuilder; L1 L7 3    MAXSTACK = 2    MAXLOCALS = 4

以上是"Java代码中字符串拼接方式有哪些"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

0