先前看到论坛中有人说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:),只创建了一个对象,然后只在缓冲区里面进行字符操作。本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报
悬赏问题
- ¥15 请教一下各位,为什么我这个没有实现模拟点击
- ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
- ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
- ¥20 有关区间dp的问题求解
- ¥15 多电路系统共用电源的串扰问题
- ¥15 slam rangenet++配置
- ¥15 有没有研究水声通信方面的帮我改俩matlab代码
- ¥15 ubuntu子系统密码忘记
- ¥15 保护模式-系统加载-段寄存器
- ¥15 电脑桌面设定一个区域禁止鼠标操作