麻烦先看看我整理的笔记,问题在后面,如果笔记有错请前辈们一定指出来,谢谢了!======================================================================
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 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比+的速度快一倍,百思不得其解。请前辈们指点。
解决方案 »
- 多线程问题:如何判断main线程进入dead状态??
- 一个面试题,没看明白,大家看下
- Swing 中的对话框的问题 默认情况下不支持上下键
- dom4j删除节点问题!
- 有谁去IBM面试过,一般应聘JAVA方面的,笔试考些什么?
- JAVA可不可以引用动态连接库,使用API函数。
- 晕,一个面试机会就这样失去了
- 一个applet的问题!70分,在线等待
- huangbrid就JDK配置的问题答谢各位参与和建议!flyzhen,yuechun,IMarksma,sonic616,erato,eyeieye,blackcats,awing_feeling,YANGJB
- 哪有ias下载呢??除了borland的站点???
- 关于 Java 虚拟机多线程与操作系统多线程的问题
- ???java中输出公式??
发现就算每次追加的操作都是对不同的string进行,append比+的速度快一倍,百思不得其解。请前辈们指点。
MS +的话你在内存中间要重新开辟一个内存,再进行写道缓冲区末端。这里要耗费时间。
append 方法始终将这些字符添加到缓冲区的末端;省了开辟内存的时间
for(int i = 0;i<strArray2.length;i++)
{
StringBuilder strBuilder = new StringBuilder();
strBuilder.append(str1);
strBuilder.append(str1);
strArray2[i]=strBuilder.toString();
}
这不也是每次都创建一个空间么?
+ append method took 0.516 seconds
那里速度快了
append operation took 0.359 seconds
append operation took 0.297 seconds
+ operation took 0.734 seconds基本一样
+ operation took 0.484 seconds
+ operation took 0.485 seconds
append method took 0.484 seconds
我的是AMD 3800+:
+ operation took 0.516 seconds
append method took 0.375 seconds
怪怪怪怪..我的配置:
AMD 速龙 3800+ (双核)
内存 512X2=1GB DDR2 667 (双通道)