String与StringBuffer效率的比较

String str = “”; 

for (int i=0; i<100; i++) 

str += “a”; 

 

可是你知道在内存中会产生多少的垃圾出来吗?总共会有a、aa、aaa、 

aaa….,无疑的,上述的程序虽然简单,但浪费了不少的内存,而且产 

生对象和对象的存取也会花掉不少的时间,我们加上几行程序代码来测试所 

花的时间和内存: 

long startTime = System.currentTimeMillis(); 

long startMem = Runtime.getRuntime().freeMemory(); 

 

for (int i=0; i<1000; i++) 

str += "a"; 

 

long endMem = Runtime.getRuntime().freeMemory(); 

System.out.println("Use memory: "+ (startMem - endMem)); 

long endTime = System.currentTimeMillis(); 

System.out.println("Use Time: "+ (endTime – startTime)); 

 

Use memory: 138688

Use Time: 16

 

上面的程序在笔者的PIII-800的计算机上跑,平均花了50 ms和151256 bytes 

的内存,时间还好,但内存使用量算蛮大的了。那我们要如何来改进 

让程序更有效率呢?因为String对象是不可修改的,可是程序中又常需要 

这样的一个动作,所以Java提供了另外一个类别,专门来处理字符串运算用 

的,这个类别就叫作StringBuffer。StringBuffer类别提供了很多方法来 

做字符串的运算,但如附加、删除、插入、反转、替换等等…。我们就用 

StringBuffer类别所提供的附加(append)方法来做到跟上面那个例子同样 

的结果: 

StringBuffer sb = new StringBuffer(); 

long startTime = System.currentTimeMillis(); 

long startMem = Runtime.getRuntime().freeMemory(); 

 

for (int i=0; i<1000; i++) 

sb.append(“a”); 

 

long endMem = Runtime.getRuntime().freeMemory(); 

System.out.println("Use memory: "+ (startMem - endMem)); 

long endTime = System.currentTimeMillis(); 

 

Use memory: 4976

Use Time: 0

修改过的程序在笔者计算机上跑,平均花了0 ms和4854 bytes的内存。 

0 ms?!多跑几次有时会到10 ms,要看你计算机CPU目前的负载如何,不 

过跟前面的例子比较起来,已经算是快了,而且内存也使用的非常少 

。这只是个小小的例子,如果字符串量再大一点,两者的差异会更明显。 

 

所以结论就是,如果你的程序中会对字符串做大量的修改时,请改用 

StringBuffer类别,它会明显示改进你程序的效率。至于StringBuffer 

类别所提供的方法详细的使用说明,就请自行参阅Java API。

 

****************************************************************************


[转自]http://www.newsmth.net/pc/pccon.php?id=1427&nid=55836&s=all


好几天没有来发日志了,主要是因为这两天都在陪mm,嘿嘿所以今天小小偷懒一下,把我下午总结的一个组内报告发上来吧,hoho下面就开始吧!(别扔蔬菜和鸡蛋,我错了还不行么……)

在java中java.lang.String类是最常用但也是最容易被滥用的一个类,它也是导致代码性能低下的一个主要原因。所以今天就来说说和String使用相关的一些不得不注意的地方:

例1 String的相加操作

一个效率低下的例子如下:

代码段1

String s1 = "Testing String";

String s2 = "Concatenation Performance";

String s3 = s1 + " " + s2;

因为java中的String类不可变的(immutable),所以必须使用StringBuffer作为中间临时存储。这一段代码的性能损耗在最后相加的时候,程序内部生成和销毁了一次StringBuffer对象,以及一个String对象,见下面的代码被编译之后的版本:

代码段2

StringBuffer s = new StringBuffer();

s.append("Testing String");

s.append(" ");

s.append("Concatenation Performance");

String s3 = s.toString(); 

而StringBuffer类的默认构造函数为:public StringBuffer() { this(16); }

也就是说StringBuffer创建的时候默认的长度是16,以后当进行append的时候,如果空间不够,则会调用私有函数将空间加倍并将内容拷贝到新的空间中,代码如下:

代码段3

public synchronized StringBuffer append(String str) {

 if (str == null) { 

    str = String.valueOf(str);

  }

 int len = str.length();

 int newcount = count + len;

 if (newcount > value.length) expandCapacity(newcount);

 str.getChars(0, len, value, count);

 count = newcount; return this;

}

在代码段2(以及在代码段1的编译结果中),由于字符串追加操作的最后结果是“Testing String Concatenation Performance”,它有40个字符,StringBuffer的存储能力必须扩展两次,从而导致了两次代价昂贵的复制操作,这个是速度降低的致命原因。所以至少我们可以进行的一个优化是分配一个初始大小大于等于40的StringBuffer对象进行追加:

代码段4

StringBuffer s = new StringBuffer(45);

s.append("Testing String");

s.append(" ");

s.append("Concatenation Performance");

String s3 = s.toString();

例2 避免多次的String相加:
看下面的例子:

代码段5

String s = "";

int sum = 0;

for(int I=1; I<10; I++) {

  sum += I;

  s = s + "+" +I 

 }

s = s + "=" + sum; 

这段代码中循环中每次都进行了一次StringBuffer对象和String对象的创建和销毁,这样的开销很大而且不必要,如果使用下面的代码进行改进,就可以避免这样的情况:

代码段6

StringBuffer sb = new StringBuffer();

int sum = 0;

 for(int I=1;

 I<10; I++){

  sum + = I;

  sb.append(I).append("+");

 }

String s = sb.append("=").append(sum).toString();

例3

小结

得到的结论是:如果对字符串中的内容经常进行操作,特别是内容要修改时,那么使用StringBuffer,如果最后需要String,那么使用StringBuffer的toString()方法进行转换


*********************************************************************


[附:一个论坛上的讨论 更加详细]http://topic.csdn.net/t/20050610/10/4072734.html

 

 

http://blog.163.com/hbkjdx205@126/blog/static/31578101200701210393688/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值