资讯专栏INFORMATION COLUMN

String、StringBuilder、StringBuffer 拼接测试

20171112 / 2542人阅读

摘要:测试拼接速度测试的结果在循环中,拼接字符串的速度远低于和利用查看字节码文件,寻找其中的差异命令行执行结果可以看出,拼接的时候也是通过的方法进行拼接的产生差异的原因是,在每次循环中,拼接的时候都了一个是线程安全的,只比稍慢了一点若不是

String、StringBuilder、StringBuffer 测试拼接速度
@Test
public void testString() {
    long before = System.currentTimeMillis();
    String s = "";
    for (int i = 0; i < 100000; i++) {
        s += "a";
    }
    long after = System.currentTimeMillis();
    System.out.println("String cost: " + (after - before));
}

@Test
public void testStringBuilder() {
    long before = System.currentTimeMillis();
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < 100000; i++) {
        sb.append("a");
    }
    long after = System.currentTimeMillis();
    System.out.println("StringBuilder cost: " + (after - before));
}

@Test
public void testStringBuffer() {
    long before = System.currentTimeMillis();
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < 100000; i++) {
        sb.append("a");
    }
    long after = System.currentTimeMillis();
    System.out.println("StringBuffer cost: " + (after - before));
}

测试的结果:

    StringBuilder cost: 5
    StringBuffer cost: 9
    String cost: 14029

在循环中,String 拼接字符串的速度远低于 StringBuilder 和 StringBuffer

利用 javap 查看字节码文件,寻找其中的差异

命令行执行

javap -c StringTest.class

结果可以看出,String 拼接的时候也是通过 StringBuilder 的 append 方法进行拼接的

产生差异的原因是,在每次循环中,String 拼接的时候都 new 了一个 StringBuilder

StringBuffer 是线程安全的,只比 StringBuilder 稍慢了一点

public void testString();
Code:
0: ldc           #2                  // String
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: ldc           #11                 // int 100000
8: if_icmpge     37
11: new           #4                  // class java/lang/StringBuilder
14: dup
15: invokespecial #5                  // Method java/lang/StringBuilder."":()V
18: aload_1
19: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: ldc           #9                  // String a
24: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
27: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
30: astore_1
31: iinc          2, 1
34: goto          5
37: return

public void testStringBuilder();
Code:
0: new           #4                  // class java/lang/StringBuilder
3: dup
4: invokespecial #5                  // Method java/lang/StringBuilder."":()V
7: astore_1
8: iconst_0
9: istore_2
10: iload_2
11: ldc           #11                 // int 100000
13: if_icmpge     29
16: aload_1
17: ldc           #9                  // String a
19: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: pop
23: iinc          2, 1
26: goto          10
29: return

public void testStringBuffer();
Code:
0: new           #12                 // class java/lang/StringBuffer
3: dup
4: invokespecial #13                 // Method java/lang/StringBuffer."":()V
7: astore_1
8: iconst_0
9: istore_2
10: iload_2
11: ldc           #11                 // int 100000
13: if_icmpge     29
16: aload_1
17: ldc           #9                  // String a
19: invokevirtual #14                 // Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
22: pop
23: iinc          2, 1
26: goto          10
29: return

若不是循环,String 和 StringBuilder 拼接的速度是差不多的

java 测试代码

@Test
public void string() {
    String s = "";
    String ss = "cc";
    s += "a" + "b" + ss;
}
    
@Test
public void stringBuilder() {
    StringBuilder sb = new StringBuilder();
    String ss = "cc";
    sb.append("a").append("b").append(ss);
}

字节码

public void string();
Code:
0: ldc           #2                  // String
2: astore_1
3: ldc           #3                  // String cc
5: astore_2
6: new           #4                  // class java/lang/StringBuilder
9: dup
10: invokespecial #5                  // Method java/lang/StringBuilder."":()V
13: aload_1
14: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: ldc           #7                  // String ab
19: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: aload_2
23: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
26: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
29: astore_1
30: return

public void stringBuilder();
Code:
0: new           #4                  // class java/lang/StringBuilder
3: dup
4: invokespecial #5                  // Method java/lang/StringBuilder."":()V
7: astore_1
8: ldc           #3                  // String cc
10: astore_2
11: aload_1
12: ldc           #9                  // String a
14: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: ldc           #10                 // String b
19: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: aload_2
23: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
26: pop
27: return

原因是同样只 new 了一个 StringBuilder,使用的也是它的 append 方法

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/67263.html

相关文章

  • 从字节码角度看StringStringBuffer、StringBuilder的不同

    摘要:官方说明将一个或多个类文件进行分解。显示静态常量为每个类中的方法打印反汇编代码例如字节码指令组成。在结果的行直接进行多次的拼接看看最后编译会是神马的这句话是对应声明了一个,然后每次拼接实际使用的是的方法。 Oracle官方说明: javap 将一个或多个类文件进行分解。 使用简要说明 javap [options] classfile... options 命令行选项,详细查看后面...

    wua_wua2012 评论0 收藏0
  • 为什么不建议在for循环中使用"+"进行字符串拼接

    摘要:使用可以方便的对字符串进行拼接。该方法使用进行声明,说明是一个线程安全的方法。所以,阿里巴巴开发手册建议循环体内,字符串的连接方式,使用的方法进行扩展。但是,还要强调的是如果不是在循环体中进行字符串拼接的话,直接使用就好了。 摘要: 学习阿里巴巴Java开发手册。 原文:为什么阿里巴巴不建议在for循环中使用+进行字符串拼接 微信公众号:Hollis Fundebug经授权转载,...

    caoym 评论0 收藏0
  • Java 字符串拼接效率分析及最佳实践

    摘要:两个字符串拼接直接调用性能最好。关于的其他最佳实践用时总是把能确定不为空的变量写在左边,如使用判断空串,避免空指针异常。在需要把其他对象转换为字符串对象时,使用而不是直接调用方法,因为前者已经对空值进行检测了,不会抛出空指针异常。 本文来源于问题 Java字符串连接最佳实践? java连接字符串有多种方式,比如+操作符,StringBuilder.append方法,这些方法各有什么优...

    BakerJ 评论0 收藏0
  • StringStringBuilder、StringBuffer的爱恨情仇

    摘要:当然大多数情况下就是我们是在单线程下进行的操作,所以大多数情况下是建议用而不用的,就是速度的原因。 第三阶段 JAVA常见对象的学习 StringBuffer和StringBuilder类 (一) StringBuffer类的概述 (1) 基本概述 下文以StringBuffer为例 前面我们用字符串做拼接,比较耗时并且也耗内存(每次都会构造一个新的string对象),而这种拼接操作又...

    stormjun 评论0 收藏0
  • StringString / StringBuffer / StringBuilder 三者的功能

    摘要:不指定容量会显著降低性能一般使用在方法内部来完成类似功能,因为是线程不安全的,所以用完以后可以丢弃。主要用在全局变量中相同情况下使用相比使用仅能获得左右的性能提升,但却要冒多线程不安全的风险。 String 作为最基础的引用数据类型,日常的开发中被大量的使用。基于不可变的特性,一旦被过度地使用,堆内存就会负荷不堪,甚至影响性能,为此,Java 设计者特意为 String 在方法区中开辟...

    icattlecoder 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<