CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
可用分押宝游戏火热进行中... 专题改版:Java Web 专题
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  Java >  J2SE / 基础类

String 和 StringBuffer的效率问题

楼主whyy0(用心)2005-06-10 10:15:51 在 Java / J2SE / 基础类 提问

① 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 有什么区别,用途有什么不同?

关键词

  • 内存
  • 数据
  • 连接
  • stringbuffer
  • 字符串
  • endmem
  • startmem
  • 效率
  • aa
  • endtime

得分解答快速导航

  • 帖主:whyy0
  • ChDw

相关链接

  • CSDN Java频道
  • Java类图书
  • Java类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
世纪乐知(北京)网络技术有限公司 版权所有, 京 ICP 证 020026 号
北京创新乐知广告有限公司 提供技术支持
Copyright © 2000-2007, CSDN.NET, All Rights Reserved
GongshangLogo