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 关于#hadoop#的问题
  • ¥15 (标签-Python|关键词-socket)
  • ¥15 keil里为什么main.c定义的函数在it.c调用不了
  • ¥50 切换TabTip键盘的输入法
  • ¥15 可否在不同线程中调用封装数据库操作的类
  • ¥15 微带串馈天线阵列每个阵元宽度计算
  • ¥15 keil的map文件中Image component sizes各项意思
  • ¥20 求个正点原子stm32f407开发版的贪吃蛇游戏
  • ¥15 划分vlan后,链路不通了?
  • ¥20 求各位懂行的人,注册表能不能看到usb使用得具体信息,干了什么,传输了什么数据