String 和 StringBuffer的效率问题
① String aa = "aa" + "bb" + "cc";
② StringBuffer aa = new StringBuffer("aa" + "bb" + "cc");
③ StringBuffer aa = new StringBuffer();
aa.append("aa");
aa.append("bb");
aa.append("cc");
以上3个方案哪个效率高??为什么??
问题点数:20、回复次数:40Top
1 楼ChDw(米)回复于 2005-06-10 10:24:05 得分 20
呵呵,如果你这样写当然是①
因为编译器已经直接自动计算好了,已经不是在运行的时候才进行+了
StringBuffer比String好,主要是在一个循环中才会明显,如果直接就是一行过没有在循环体内就没有什么问题Top
2 楼chuanyuan88(船员-逆水行舟,不进则退!)回复于 2005-06-10 10:50:31 得分 0
mark,
chDw(米)讲得很有道理Top
3 楼yaohao803(长期不锻炼的结果,体重130!~~还好不是公斤!)回复于 2005-06-10 11:17:27 得分 0
3效率高
首先我们要明白String+String在内存中的动作
比如:
String a = "a";
String b = "b";
String c = a + b;
实际上a+b的时候并不会把a和b所占的内存回收掉,而是a,b,c都占用一定的内存
而StringBuffer则不同.
public class performance {
long startTime;
long startMem;
long endTime;
long endMem;
long time;
long mem;
public void count() {
time = endTime-startTime;
mem = startMem - endMem;
}
public String toString() {
return "测试内存使用和运行时间";
}
public void print() {
System.out.println("Use memory: "+ mem);
System.out.println("Use Time: "+ time);
}
public void Start() {
startTime = System.currentTimeMillis();
startMem = Runtime.getRuntime().freeMemory();
}
public void End() {
endMem = Runtime.getRuntime().freeMemory();
endTime = System.currentTimeMillis();
}
}
你可以写一个main方法测测
Top
4 楼wwm217(wwm)回复于 2005-06-10 11:44:01 得分 0
小数据量无所谓,大数据量时用StringBuffer,速度会快很多(不是一个数量级)Top
5 楼whyy0(用心)回复于 2005-06-10 17:03:54 得分 0
要是我在这3句话的外面套上循环500次呢??
①for(int i=0; i<500; i++){
String aa = "aa" + "bb" + "cc";
}
②
for(int i=0; i<500; i++){
StringBuffer aa = new StringBuffer("aa" + "bb" + "cc");
}
③
{ StringBuffer aa = new StringBuffer();
aa.append("aa");
aa.append("bb");
aa.append("cc");
}
哪个快??Top
6 楼whyy0(用心)回复于 2005-06-10 17:05:14 得分 0
我个人认为如果字符串比较长的话,3应该是最慢,不过是我想的,没有测试过Top
7 楼cat_871017(零下九度)回复于 2005-06-10 17:52:34 得分 0
3Top
8 楼cat_871017(零下九度)回复于 2005-06-10 17:54:50 得分 0
楼上的楼上讲反了,显然大数据量时StringBuffer 会快很多,因为String 在作变动时都要产生新的String ,相当于要把整个字符串拷贝一便,而StrigBuffer 则不用Top
9 楼ukey235(a)回复于 2005-06-10 18:01:28 得分 0
学习Top
10 楼pfzl_j()回复于 2005-06-10 18:17:15 得分 0
收藏!Top
11 楼cshephy(你们为谁举杯?)回复于 2005-06-10 18:30:03 得分 0
老师说一般都用StringBufferTop
12 楼yonghar(http://www.xio.name)回复于 2005-06-10 18:38:07 得分 0
大对象的时候必须要使用StringBuffer,不然你会付出代价的。Top
13 楼chenmoderen(黑子)回复于 2005-06-10 19:46:01 得分 0
String 何 StringBuffer的区别:
String 是不变类 即是 final类型。
所以
每次产生String 时 都会在内存内 产生一份拷贝。
比如
String a="aaa";
String b="bb";
String c=a+b;
那么内存中将有 三个对象 产生三个副本。
而StringBuffer 则不同
它将2个字符串连接
而不会进行新的内存分配
Top
14 楼starwill(流浪的沙)回复于 2005-06-10 20:29:43 得分 0
楼上说的大部分都有道理,在此我要补充一点~~
StringBuffer是可变类,处理字符串相加或者改变字符串时不会分配新的内存~~这点上它有优势~~
String类是不可变类,处理字符串会新建一个对象(分配内存),但JAVA虚拟机对其进行了优化~~
使String类可以共享内存:
如 String a = "abc"; String b = "abc",此时,a和b共享内存(指向同一个内存地址)
不信你可以用System.out.println(a==b)试一下~~所以,此时内存中只建了一个"abc"的字符串~
这是String类的优势~~
具体哪个效率高还真难说,不同的情况会有不同的结果~~
Top
15 楼danceflash(Wine)回复于 2005-06-10 20:38:29 得分 0
大数据量的字符串连接时,StringBuffer会有明显的效率提高
小数据量的时候无所谓啦就Top
16 楼slh002(呵呵)回复于 2005-06-10 20:59:22 得分 0
在一般情况下String与 stringBuffer二种写法效率是一样,因为String通过编译器自动优化后,自动转化为StringBuffer实现,且默认容量为10. 因此,只有在 设定StringBufer()中的初始容量>10之后,才比String更有效率.
应用StringBuffer,关键在于根据处理数据大小,设定一个适当的初始容量.Top
17 楼WinFastNcr(随她去吧!)回复于 2005-06-10 21:06:23 得分 0
项Top
18 楼Heart_Broken(戒你Ю太难)回复于 2005-06-10 22:42:46 得分 0
照你这么写的话,我觉得差不多,数据量不大,它们之间的差异更应该体现在数据量大的情况下,一般小数据量也差不多!
在选择用String对象还是用StringBuffer对象来代表一个字符串时,如果该字符串不会变更,则总是使用String对象,这将提高性能.
如果程序频繁的执行字符串连接操作.或其他的字符串修改操作.则使用StringBuffer类来实现.可以提高效率.Top
19 楼whyy0(用心)回复于 2005-06-13 16:54:30 得分 0
大家的说法全都错了,我已经测试过了,是1最快,2其次,3最慢
public class Test {
long startTime;
long startMem;
long endTime;
long endMem;
long time;
long mem;
public static void main(String[] args) {
Test a = new Test();
a.Start();
for (int i = 0; i < 500; i++) {
//StringBuffer aa = new StringBuffer("aaaaaaaaaaaaaaaaa" + "bbbbbbbbbbbbbbbbbbbbbb" + "ccccccccccccccccccccc");
// StringBuffer aa = new StringBuffer();
// aa.append("aaaaaaaaaaaaaaaaa");
// aa.append("bbbbbbbbbbbbbbbbbbbbbb");
// aa.append("ccccccccccccccccccccc");
String aa = "aaaaaaaaaaaaaaaaa" + "bbbbbbbbbbbbbbbbbbbbbb" + "ccccccccccccccccccccc";
}
a.End();
a.count();
a.toString();
a.print();
}
public void count() {
time = endTime - startTime;
mem = startMem - endMem;
}
public String toString() {
return "测试内存使用和运行时间";
}
public void print() {
System.out.println("Use memory: " + mem);
System.out.println("Use Time: " + time);
}
public void Start() {
startTime = System.currentTimeMillis();
startMem = Runtime.getRuntime().freeMemory();
System.out.println("start memory: " + startMem);
System.out.println("start Time: " + startTime);
}
public void End() {
endMem = Runtime.getRuntime().freeMemory();
endTime = System.currentTimeMillis();
System.out.println("end memory: " + endMem);
System.out.println("end Time: " + endTime);
}
大家谁不信可以试试Top
20 楼whyy0(用心)回复于 2005-06-13 17:01:43 得分 0
原因是什么呢??因为是每次循环都做了初始化,而不是在一个字符串上座修改
第一个建立了4个String对象,但是aa内存分配是一次完成的
第2个建立了3个String对象,一个StringBuffer,StringBuffer的建立是初始化的String+16,所以内存占用量比1大,建立一个StringBuffer要比String慢,所以速度也不行
第3个,建立了3个String对象,一个StringBuffer,StringBuffer的初始大小是16,如果第一个append的字符串>16要重新分配内存,一次,大小是第一个子符串的大小+16,已此类推,如果append的字符串比较大的话,第3个方案要分配3次内存,所以速度最慢Top
21 楼yonghar(http://www.xio.name)回复于 2005-06-13 17:52:04 得分 0
一个血的教训:
曾经用sax解析一份大的xml文件的时候,把值放在String,用+连接。
运行一段时间,程序总会等待好几分钟来回收垃圾,而且这个时候什么事情都干不了的。
等待几分钟意味着时间是正常的100倍量级,甚至千倍。Top
22 楼sublive(一只泡泡)回复于 2005-06-13 18:41:27 得分 0
1楼的已经说的很清楚了。
大家都知道StringBuffer在连接字符方面效率高,但还要看是什么情况下用。Top
23 楼ChDw(米)回复于 2005-06-14 09:35:23 得分 0
那是因为你的测试程序写得不正确造成的,
StringBuffer sb = new StringBuffer();
for(int i = 0; i < 10000; i++)
sb.append("FFFFF");
和
String a = "";
for(int i = 0; i < 10000; i++)
a += "FFFFF";
你这样就可以发现其中的巨大差异Top
24 楼microunit(微量单位)回复于 2005-06-14 09:54:16 得分 0
学习Top
25 楼mbh0210(独孤求败)回复于 2005-06-14 10:56:04 得分 0
写程序也有几个月了,还没有仔细的研究过这些东西啊,惭愧,学习中.....Top
26 楼HStone(石头)回复于 2005-06-14 11:36:38 得分 0
顶一下 ChDw(米)
把变量定义放在循环体外是个很基础的优化常识喔!Top
27 楼bigc2001(大C)回复于 2005-06-14 12:50:51 得分 0
Mark MarkTop
28 楼whyy0(用心)回复于 2005-06-15 17:24:58 得分 0
ChDw(米) 首先感谢你的回答
我当然知道什么样的情况下有巨大差异,我就使要问这样的特殊情况,只是想给大家提个醒,不要只记结果,不分析什么情况。
你可以自己看看我的问题,再看看我的测试程序,你怎么可以说我写的不对呢??Top
29 楼airhand(暴风雨)回复于 2005-06-15 17:38:54 得分 0
3最好,使用的空间最少,前两种要浪费很多空间,虽然不用你回收,但也是不经济的。Top
30 楼supernovaex(超新星)回复于 2005-06-15 18:17:55 得分 0
MarkTop
31 楼ChDw(米)回复于 2005-06-15 18:21:54 得分 0
我为什么说你的不正确,这是因为
for (int i = 0; i < 500; i++) {
String aa = "aaaaaaaaaaaaaaaaa" + "bbbbbbbbbbbbbbbbbbbbbb" + "ccccccccccccccccccccc";
}
这样做法,首先编译器自动帮助你优化成
for (int i = 0; i < 500; i++) {
String aa = "aaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccc";
}
所以在这个过程中,根本没有生成任何对象(那个是字符串常量,只会在类中存在一份,aa每次都指向这个常量罢了),所以没有任何拷贝动作
for (int i = 0; i < 500; i++) {
StringBuffer aa = new StringBuffer("aaaaaaaaaaaaaaaaa" + "bbbbbbbbbbbbbbbbbbbbbb" + "ccccccccccccccccccccc");
}
优化成:
for (int i = 0; i < 500; i++) {
StringBuffer aa = new StringBuffer("aaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccc");
}
即,除了一个常量以外,还会在循环中生成一个StringBuffer对象,但是它是在构造函数中已经完成了,没有后续函数调用!
最后一种 :
for (int i = 0; i < 500; i++) {
StringBuffer aa = new StringBuffer();
aa.append("aaaaaaaaaaaaaaaaa");
aa.append("bbbbbbbbbbbbbbbbbbbbbb");
aa.append("ccccccccccccccccccccc");
}
编译器无法优化(它没有这么聪明),所以这种方法会有三个字符串常量,并每次循环有构造函数外还额外调用多三次方法
从上述可以看到,这个根本是因为编译器的优化造成的
如果你将程序改成
String constA = "aaaaaaaaaaaaaaaaa";
String constB = "bbbbbbbbbbbbbbbbbbbbbb";
String constC = "ccccccccccccccccccccc";
再将后面相应的换成上面的constA, constB, constC,
你就会发现这三者的速度是相当的Top
32 楼ChDw(米)回复于 2005-06-15 18:29:08 得分 0
String constA = "aaaaaaaaaaaaaaaaa";
String constB = "bbbbbbbbbbbbbbbbbbbbbb";
String constC = "ccccccccccccccccccccc";
long t1 = System.currentTimeMillis();
for (int i = 0; i < 500000; i++) {
1. //String aa = constA + constB + constC;
2. //StringBuffer aa = new StringBuffer(constA + constB + constC);
3. StringBuffer aa = new StringBuffer();
aa.append(constA);
aa.append(constB);
aa.append(constC);
4. StringBuffer aa = new StringBuffer(constA);
aa.append(constB);
aa.append(constC);
}
long t2 = System.currentTimeMillis();
System.out.println("(T2-T1):" + (t2 - t1));
在我的机器上面
1. 用时 700ms
2. 用时 1100ms
3. 用时 620ms
4. 用时 550msTop
33 楼leihailin(harly)回复于 2005-06-15 20:22:55 得分 0
请问 ChDw(米) 学了多长时间的JAVA了啊
没别的意思,只是感觉你分析的不错,我是新手,Top
34 楼leihailin(harly)回复于 2005-06-15 20:25:29 得分 0
请问编译器怎么优化下面的代码
String a="afdsafda";
String a=a+"fs";
还有更有效率的方法做到这件事情么Top
35 楼rswhs(若是我回首)回复于 2005-06-15 20:59:22 得分 0
up up up
有点收获Top
36 楼Kala_Yang(卡拉*杨)回复于 2005-06-15 21:28:01 得分 0
谢谢了,我也长进了不少,互相学习,互相鼓励了,顶!Top
37 楼ChDw(米)回复于 2005-06-16 10:19:27 得分 0
String a = "afdsafda";
String b = a + "fs";
这样的代码,编译器无法优化
但是这样可以:
final String a = "afdsafda";
final String b = a + "fs";Top
38 楼jyy7751(wish i could fly)回复于 2005-06-16 11:04:35 得分 0
数据量大时用StringBuffer,很快的Top
39 楼whyy0(用心)回复于 2005-06-16 14:11:04 得分 0
ChDw(米)
看了你的讲解是明白了不少。
但是我还是不明白1和2比3多消耗的时间在那里呢??Top
40 楼whyy0(用心)回复于 2005-06-16 14:31:42 得分 0
我知道了在 + 号上Top
相关问题
- String和StringBuffer的问题
- String和StringBuffer的区别!?!糊了
- 关于string和stringbuffer的问题!
- 请问String和StringBuffer有什么区别?
- 各位高手:String 和 StringBuffer这两个类有什么区别。
- 出学JAVA,关于String和StringBuffer的问题.
- String与StringBuffer的区别
- new 和 malloc效率比较
- 程序里面的string,StringBuilder,StringWriter,MemoryStream哪种效率高?
- 请问string 和stringbuffer class 有什么区别,用途有什么不同?




