hunterli0408 2010-07-07 20:59
浏览 208
已采纳

高分求证:StringBuffer和String的性能比较

先前看到论坛中有人说JDK5下,String的连加操作会被JVM优化为StringBuffer.append()操作,因此拼装String时,两者的性能是一样的。今天闲着没事,写了段小程序测试了一下,对字母A进行1100次拼接,发现StringBuffer的性能比String连加要高出将近100倍,不知是怎么回事。各位给看看,附件是我的测试程序。

  • 写回答

13条回答 默认 最新

  • 「已注销」 2010-07-10 13:02
    关注

    JVM优化是对的,我这里没有JDK5.0.用的是6.0测试的,6.0对于String的连加采用的是StringBuilder优化的,按说优化了为什么StringBuffer的性能还是那么好呢。下面就分析一下。测试用例如下:
    [code="java"]/**

    • @author 飞雪无情
    • @since 2010-7-10
      */
      public class TestStringBuffer {

      public void testString(){
      String s="";
      for(int i=0;i<10000;i++){
      s+=i;
      }
      }
      public void testStringBuffer(){
      StringBuffer s=new StringBuffer("");
      for(int i=0;i<10000;i++){
      s.append(i);
      }
      }

    }[/code]
    这两个函数分别演示了string的连加和StringBuffer操作,执行测试,我本机上testString()600多毫秒,testStringBuffer()不超过20毫秒。下面就分析为什么,我们采用JDK的反汇编工具javap,执行javap -c TestStringBuffer后我们看到CMD输出,我们挑重要的看,先看方法testString。
    [code="java"]public void testString();
    Code:
    0: ldc #19; //String
    2: astore_1
    3: iconst_0
    4: istore_2
    5: goto 30
    8: new #21; //class java/lang/StringBuilder
    11: dup
    12: aload_1
    13: invokestatic #23; //Method java/lang/String.valueOf:(Ljava/lang/Objec
    t;)Ljava/lang/String;
    16: invokespecial #29; //Method java/lang/StringBuilder."":(Ljava/la
    ng/String;)V
    19: iload_2
    20: invokevirtual #32; //Method java/lang/StringBuilder.append:(I)Ljava/la
    ng/StringBuilder;
    23: invokevirtual #36; //Method java/lang/StringBuilder.toString:()Ljava/l
    ang/String;
    26: astore_1
    27: iinc 2, 1
    30: iload_2
    31: sipush 10000
    34: if_icmplt 8
    37: return[/code]
    我就不一行行分析了,有兴趣的可以看看相关知识,分析关键的,循环从“2:”开始到“34:”看第“8:”,创建了一个StringBuilder,然后使用append方法("第20:")进行String连加的优化,最要注意的是 创建这个StringBuilder,是在循环里面,也就是说我们循环多少次就会创建多少个StringBuilder,这就很影响性能(创建对象是很耗性能的).然后我们看testStringBuffer方法。
    [code="java"]public void testStringBuffer();
    Code:
    0: new #46; //class java/lang/StringBuffer
    3: dup
    4: ldc #19; //String
    6: invokespecial #48; //Method java/lang/StringBuffer."":(Ljava/lan
    g/String;)V
    9: astore_1
    10: iconst_0
    11: istore_2
    12: goto 24
    15: aload_1
    16: iload_2
    17: invokevirtual #49; //Method java/lang/StringBuffer.append:(I)Ljava/lan
    g/StringBuffer;
    20: pop
    21: iinc 2, 1
    24: iload_2
    25: sipush 10000
    28: if_icmplt 15
    31: return[/code]
    看看多么简单,在循环开始前创建好StringBuffer,然后再循环里面调用append方法(第17:),只创建了一个对象,然后只在缓冲区里面进行字符操作。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(12条)

报告相同问题?

悬赏问题

  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作