读书人

一些字符串追加的有关问题(+操作符和a

发布时间: 2012-03-07 09:13:51 作者: rapoo

一些字符串追加的问题(+操作符和append)。
麻烦先看看我整理的笔记,问题在后面,如果笔记有错请前辈们一定指出来,谢谢了!

======================================================================
String str1 = "a ";
String str2 = "b ";
String str3 = str1 + str2;
======================================================================
这里str3的赋值过程不是表面上看起来的那么简单。我们来看看它的字节码:
======================================================================
L2 (6)
LINENUMBER 9 L2
NEW java/lang/StringBuilder
DUP
ALOAD 1
INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String;
INVOKESPECIAL java/lang/StringBuilder. <init> (Ljava/lang/String;)V
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
ASTORE 3
======================================================================
先构造一个StringBuilder对象(这是在1.5以及之后版本的jdk上解释后的字节码,jdk1.4构造的是StringBuffer对象),然后通过引用str1取出对应的值“a”为字符串类型,作为参数来构造这个StringBuilder,接着调用StringBuilder的append方法,以引用str2对应的值“b”为参数来追加字符串,最后调用它的toString转化为String类型保存。(jvm的指令我不是很懂,说得不妥当或者有欠缺的地方请一定指出来,谢谢!)

如果两个字符串变量相加的操作很频繁,每次操作都要创建一个StringBuilder,并且将它转化为String类型,之后不用的对象又需要GC来回收,会耗费很多的资源。

而如果用以下方法:
======================================================================
StringBuilder str4 = new StringBuilder();
str4.append(str1);
str4.append(str2);
======================================================================
我们先来看看它的字节码:
======================================================================
L4 (20)
LINENUMBER 13 L4
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder. <init> ()V
ASTORE 4
L5 (25)
LINENUMBER 14 L5
ALOAD 4
ALOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
POP
L6 (30)
LINENUMBER 15 L6
ALOAD 4
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
POP
======================================================================
看起来似乎比上面的那种方法操作更麻烦。但仔细看看,用这第二种方法追加字符串,无论加多少次,都只需要在一开始创建一个StringBuilder对象,而且不用调用toString方法,只有在需要取值的时候,人为地去调用它的toString方法。


现在问题来了:
按这么说的话, 用+和用append的区别也只有在对单个string进行不断的追加的时候才会很明显吧。
如果每次的追加操作都是对不同的string呢?是不是两者几乎没有区别?

而我又做了以下试验:

public class Test {
public static void main(String[] args)
{
String[] strArray1 = new String[500000];
String[] strArray2 = new String[500000];



String str1 = "a ";

long beginTime = System.currentTimeMillis();

for(int i = 0;i <strArray1.length;i++)
{
strArray1[i]=str1+str1;
}

long endTime = System.currentTimeMillis();

System.out.println( "+ operation took "+(endTime-beginTime)/1000.0+ " seconds ");

beginTime = System.currentTimeMillis();

for(int i = 0;i <strArray2.length;i++)
{
StringBuilder strBuilder = new StringBuilder();
strBuilder.append(str1);
strBuilder.append(str1);
strArray2[i]=strBuilder.toString();
}

endTime = System.currentTimeMillis();

System.out.println( "+ operation took "+(endTime-beginTime)/1000.0+ " seconds ");
}
}


发现就算每次追加的操作都是对不同的string进行,append比+的速度快一倍,百思不得其解。请前辈们指点。

[解决办法]

发现就算每次追加的操作都是对不同的string进行,append比+的速度快一倍,百思不得其解。请前辈们指点。
MS +的话你在内存中间要重新开辟一个内存,再进行写道缓冲区末端。这里要耗费时间。
append 方法始终将这些字符添加到缓冲区的末端;省了开辟内存的时间
[解决办法]
String 每次都要创建一个空间,而StringBuffer只创建一次.
[解决办法]
+ operation took 0.515 seconds
+ append method took 0.516 seconds
那里速度快了
[解决办法]
String是 "轻量级 "的,相对于string,StringBuilder是 "超重量级 "的.....这么说不明白的话你可以定义大量的相同数量的StringBuilder和String,(一定要每个都给个引用,也就是说不让它自动回收),你看下内存的空间和时间就知道了
[解决办法]
+ operation took 0.75 seconds
+ operation took 0.734 seconds

基本一样
[解决办法]
我的是这个结果:

+ operation took 0.531 seconds
+ operation took 0.484 seconds

读书人网 >J2SE开发

热点推荐