String, StringBuffer 和Stringbuilder的区别以及性能差异

JAVA平台提供它们可以储存和操作字符串

String 字符串常量
StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)

总的测试结果如下:

测试程序:

 

private static void teststring() {
        String text = "";
        StringBuffer sbf = new  StringBuffer("");
        StringBuilder sbi = new  StringBuilder("");
        long s1 = System.currentTimeMillis();
        for (int i = 0; i < 50000; i++) {
         sbi.append(i);
        }
        long s11 = System.currentTimeMillis();
        System.out.println("StringBuilder:" + (s11 - s1));
       
        s1 = System.currentTimeMillis();
        for (int i = 0; i < 50000; i++) {
         sbf.append(i);
        }
        s11 = System.currentTimeMillis();
        System.out.println("StringBuffer:" + (s11 - s1));
       
        s1 = System.currentTimeMillis();
        for (int i = 0; i < 50000; i++) {
         text = text + i;
        }
        s11 = System.currentTimeMillis();
        System.out.println("String:" + (s11 - s1));
       
       
       }


private static void teststring() {
        String text = "";
        StringBuffer sbf = new  StringBuffer("");
        StringBuilder sbi = new  StringBuilder("");
        long s1 = System.currentTimeMillis();
        for (int i = 0; i < 50000; i++) {
         sbi.append(i);
        }
        long s11 = System.currentTimeMillis();
        System.out.println("StringBuilder:" + (s11 - s1));
       
        s1 = System.currentTimeMillis();
        for (int i = 0; i < 50000; i++) {
         sbf.append(i);
        }
        s11 = System.currentTimeMillis();
        System.out.println("StringBuffer:" + (s11 - s1));
       
        s1 = System.currentTimeMillis();
        for (int i = 0; i < 50000; i++) {
         text = text + i;
        }
        s11 = System.currentTimeMillis();
        System.out.println("String:" + (s11 - s1));
       
       
       }

 

测试结果:

StringBuilder:16
StringBuffer:0
String:23328

 注意:StringBuffer与StringBuilder的测试结果不准确,循环不通的次数结果不一样,理论上StringBuilder快一点。


      简要的说, String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。
而如果是使用 StringBuffer 类则结果就不一样了,每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在一般情况下我们推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。而在某些特别情况下, String 对象的字符串拼接其实是被 JVM 解释成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,而特别是以下的字符串对象生成中, String 效率是远要比 StringBuffer 快的:
String S1 = “This is only a” + “ simple” + “ test”;
StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);
你会很惊讶的发现,生成 String S1 对象的速度简直太快了,而这个时候 StringBuffer 居然速度上根本一点都不占优势。其实这是 JVM 的一个把戏,在 JVM 眼里,这个
String S1 = “This is only a” + “ simple” + “test”; 其实就是:
String S1 = “This is only a simple test”; 所以当然不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的 String 对象的话,速度就没那么快了,譬如:
String S2 = “This is only a”;
String S3 = “ simple”;
String S4 = “ test”;
String S1 = S2 +S3 + S4;
这时候 JVM 会规规矩矩的按照原来的方式去做。

        StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。
例如,如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含“startle”,而 z.insert(4, "le") 将更改字符串缓冲区,使之包含“starlet”。

        下面的文章来自:http://book.csdn.net/bookfiles/135/1001354628.shtml
StringBuilder类:
        一个String对象的长度是固定的,不能改变它的内容,或者是附加新的字符至String对象中。您也许会使用+来串联字符串以达到附加新字符或字符串的目的,但+会产生一个新的String实例。如果程序对这种附加字符串的需求很频繁,并不建议使用+来进行字符串的串联。在面向对象程序设计中,最好是能重复运用已生成的对象,对象的生成需要内存空间与时间,不断地产生String实例是一个没有效率的行为。

        J2SE 5.0提供java.lang.StringBuilder类,使用这个类所产生的对象默认会有16个字符的长度,您也可以自行指定初始长度。如果附加的字符超出可容纳的长度,则StringBuilder对象会自动增加长度以容纳被附加的字符。如果有频繁作字符串附加的需求,使用StringBuilder会让程序的效率大大提高。通过下面的简单测试程序就可以知道效能差距有多大。

Ü 范例6.5  AppendStringTest.java                                                     

Java代码   String, <wbr>StringBuffer, <wbr>StringBuilder区别与性能
  1. public class AppendStringTest {   
  2.   
  3.     public static void main(String[] args) {   
  4.   
  5.         String text "";   
  6.   
  7.     
  8.   
  9.         long beginTime System.currentTimeMillis();   
  10.   
  11.         for(int 0; 10000; i++)   
  12.   
  13.             text text i;   
  14.   
  15.         long endTime System.currentTimeMillis();   
  16.   
  17.         System.out.println("执行时间:" (endTime beginTime));   
  18.   
  19.     
  20.   
  21.         StringBuilder builder new StringBuilder("");   
  22.   
  23.         beginTime System.currentTimeMillis();   
  24.   
  25.         for(int 0; 10000; i++)   
  26.   
  27.             builder.append(String.valueOf(i));   
  28.   
  29.         endTime System.currentTimeMillis();   
  30.   
  31.         System.out.println("执行时间:" (endTime beginTime));   
  32.   
  33.     }   
  34.   
  35.  


    在范例6.5中首先使用+来串联字符串,使用System.currentTimeMillis()取得for循环执行前、后的系统时间,这样就可以得知for循环执行了多久。以下是我的计算机上的测试数据:



    执行时间:4641

    执行时间:16

    可以看到执行的时间差距很大,这说明了使用+串联字符串所带来的负担。如果有经常作附加字符串的需求,建议使用StringBuilder。事实上就范例6.5来说,第二个for循环执行时间还可以更短,因为append()也可以接受基本数据类型,所以不必特地使用String.valueOf()方法从int取得String。改为以下的方式,执行时间可以大幅缩短:

    for(int i = 0; i < 10000; i++)    builder.append(i);使用StringBuilder最后若要输出字符串结果,可以用toString()方法。可以使用length()方法得知目前对象中的字符长度,而capacity()可返回该对象目前可容纳的字符容量。另外,StringBuilder还有像insert()方法可以将字符插入指定的位置,如果该位置以后有字符,则将所有的字符往后移;deleteChar()方法可以删除指定位置的字符,而reserve()方法可以反转字符串。详细的使用可以查询java.lang.StringBuilder的API文件说明。

    StringBuilder是J2SE 5.0才新增的类,在J2SE 5.0之前的版本若有相同的需求,则使用java.lang.StringBuffer。事实上,StringBuilder被设计为与StringBuffer具有相同的操作接口。在单机非多线程(Multithread)的情况下使用StringBuilder会有较好的效率,因为StringBuilder没有处理同步(Synchronized)问题。StringBuffer则会处理同步问题,如果StringBuilder会在多线程下被操作,则要改用StringBuffer,让对象自行管理同步问题。关于多线程的概念,会在第15章详细说明。

    下面的文章来自:http://www.javaeye.com/topic/142364
    今天有空,下了scjp的题目做做,想起了一个本来想写却又没写的问题。这个问题几乎已成为面试必问题,虽然答案很简单,但回答出确又真正理解的人我觉得并不多。

    String与StringBuffer的区别?

    如果你在网上一搜,会有非常多的答案,其中最多的就是String是不可变而StringBuffer是可变的,但是这可变与不可变究竟是什么意思呢?如果你能用IDE进行debug的话,你就会发现,String实例化以后所有的属性都是final的,而StringBuffer确不是,这就是可变与不可变。下面引用SCJP的试题来解释一下这个例子。
    Java代码   String, <wbr>StringBuffer, <wbr>StringBuilder区别与性能
  1. public class Test       
  2.    public static void stringReplace (String text)       
  3.    text text.replace('j' 'i');        
  4.          
  5.           
  6.    public static void bufferReplace (StringBuffer text)       
  7.    text text.append("C");        
  8.          
  9.           
  10.     public static void main (String args[])        
  11.     String textString new String ("java");        
  12.     StringBuffer textBuffer new StringBuffer ("java");        
  13.            
  14.     stringReplace (textString);        
  15.     bufferReplace (textBuffer);        
  16.            
  17.     System.out.println (textString textBuffer);        
  18.            
  19.         



答案是 javajavaC

这是因为第七行text = text.append ("C"),append方法会改变text中的值,而text与textBuffer指向的地址是相同的。因此会打印javaC

再举个例子:

String a = "a";  //假设a指向地址0x0001

a = "b";//重新赋值后a指向地址0x0002,但0x0001地址中保存的"a"依旧存在,但已经不再是a所指向的。

因此String的操作都是改变赋值地址而不是改变值操作
loveexception:
foy 写道
SINCE1978 写道
没看懂
public static void stringReplace (String text) {   
   text = text.replace('j' , 'i');    
}——这个方法根本不起作用因为text只是引用拷贝。
似乎是在讲参数传递问题?和可变不可变对象有啥关系?


不是引用拷贝,两个对象指向同一段内存


string是不可变的。。。
比如这个:
test(x000001).replace(“j”,"i");

内部分是这样的:
Java代码

Java代码   String, <wbr>StringBuffer, <wbr>StringBuilder区别与性能
  1. String reqlace("j","i"){      
  2.  //self="java";     
  3.  // .......dosomthing     
  4.  return new String ("iava");//看到这个new 了么?     
  5.   
Java代码 String, <wbr>StringBuffer, <wbr>StringBuilder区别与性能
  1. public class Test      
  2.     public static void stringReplace(String text)      
  3.         //把textString的地址copy给text,text也指向了textString的"java"     
  4.         //text.replace('j', 'i');的结果是"iava"     
  5.         //text text.replace('j', 'i');就是重新使text指向"iava"     
  6.         //由于该方法的返回类型是void,所以原来的textString没变     
  7.         text text.replace('j', 'i');      
  8.          
  9.      
  10.     public static void bufferReplace(StringBuffer text)      
  11.         //textBuffer的地址copy给text     
  12.         //然后沿着text指向的字符串(其实也就是textBuffer指向的对象)操作,添加一个"C"     
  13.         //虽然没有任何返回,但是这个操作影响到了textBuffer所指向的字符串     
  14.         //所以上个方法打印"java",这个方法打印"javaC"     
  15.         text text.append("C");      
  16.          
  17.      
  18.     public static void main(String args[])      
  19.         String textString new String("java");      
  20.         StringBuffer textBuffer new StringBuffer("java");      
  21.      
  22.         stringReplace(textString);      
  23.         bufferReplace(textBuffer);      
  24.      
  25.         System.out.println(textString textBuffer);      
  26.          
  27.  

 

StringBuilder和StringBuffer的区别

一个String对象的长度是固定的,不能改变它的内容,或者是附加新的字符至String对象中。您也许会使用+来串联字符串以达到附加新字符或字符串的目的,但+会产生一个新的String实例。如果程序对这种附加字符串的需求很频繁,并不建议使用+来进行字符串的串联。在面向对象程序设计中,最好是能重复运用已生成的对象,对象的生成需要内存空间与时间,不断地产生String实例是一个没有效率的行为。

    J2SE 5.0提供java.lang.StringBuilder类,使用这个类所产生的对象默认会有16个字符的长度,您也可以自行指定初始长度。如果附加的字符超出可容纳的长度,则StringBuilder对象会自动增加长度以容纳被附加的字符。如果有频繁作字符串附加的需求,使用StringBuilder会让程序的效率大大提高。通过下面的简单测试程序就可以知道效能差距有多大。
 范例
 
  1. //AppendStringTest.java  
  2. public class AppendStringTest {  
  3.     public static void main(String[] args) {  
  4.         String text = " ";  
  5.           
  6.         long beginTime = System.currentTimeMillis();  
  7.         for(int i = 0; i < 10000; i++)  
  8.         text = text + i;  
  9.         long endTime = System.currentTimeMillis();  
  10.         System.out.println( "执行时间: " + (endTime - beginTime));  
  11.           
  12.         StringBuilder builder = new StringBuilder( " ");  
  13.         beginTime = System.currentTimeMillis();  
  14.         for(int i = 0; i < 10000; i++)  
  15.         builder.append(String.valueOf(i));  
  16.         endTime = System.currentTimeMillis();  
  17.         System.out.println( "执行时间: " + (endTime - beginTime));  
  18.     }  
  19. }   
 
  1. //AppendStringTest.java  
  2. public class AppendStringTest {  
  3.     public static void main(String[] args) {  
  4.         String text = " ";  
  5.           
  6.         long beginTime = System.currentTimeMillis();  
  7.         for(int i = 0; i < 10000; i++)  
  8.         text = text + i;  
  9.         long endTime = System.currentTimeMillis();  
  10.         System.out.println( "执行时间: " + (endTime - beginTime));  
  11.           
  12.         StringBuilder builder = new StringBuilder( " ");  
  13.         beginTime = System.currentTimeMillis();  
  14.         for(int i = 0; i < 10000; i++)  
  15.         builder.append(String.valueOf(i));  
  16.         endTime = System.currentTimeMillis();  
  17.         System.out.println( "执行时间: " + (endTime - beginTime));  
  18.     }  
  19. }   

    在范例中首先使用+来串联字符串,使用System.currentTimeMillis()取得for循环执行前、后的系统时间,这样就可以得知for循环执行了多久。以下是我的计算机上的测试数据:
执行时间:4641
执行时间:16
    可以看到执行的时间差距很大,这说明了使用+串联字符串所带来的负担。如果有经常作附加字符串的需求,建议使用StringBuilder。事实上就范例6.5来说,第二个for循环执行时间还可以更短,因为append()也可以接受基本数据类型,所以不必特地使用String.valueOf()方法从int取得String。改为以下的方式,执行时间可以大幅缩短:
for(int i = 0; i < 10000; i++)
builder.append(i);
    使用StringBuilder最后若要输出字符串结果,可以用toString()方法。可以使用length()方法得知目前对象中的字符长度,而capacity()可返回该对象目前可容纳的字符容量。另外,StringBuilder还有像insert()方法可以将字符插入指定的位置,如果该位置以后有字符,则将所有的字符往后移;deleteChar()方法可以删除指定位置的字符,而reserve()方法可以反转字符串。详细的使用可以查询java.lang.StringBuilder的API文件说明。
StringBuilder是J2SE 5.0才新增的类,在J2SE 5.0之前的版本若有相同的需求,则使用java.lang.StringBuffer。事实上,StringBuilder被设计为与StringBuffer具有相同的操作接口。在单机非多线程(Multithread)的情况下使用StringBuilder会有较好的效率,因为StringBuilder没有处理同步(Synchronized)问题。StringBuffer则会处理同步问题,如果StringBuilder会在多线程下被操作,则要改用StringBuffer,让对象自行管理同步问题。


 

一个关于StringBuilder与StringBuffer性能的小试验

StringBuilder 是从 Java 5 以后增加的一个字符串处理类。查看 API 文档,我们可以知道 StringBuilder 和 StringBuffer 提供同样的功能,只是 StringBuilder 不保证线程安全,所以性能比 StirngBuffer 好,并推荐在确定线程安全的情况下,尽量用 StringBuilder 。事实真是如此吗?让我们通过一个小试验来看看

试验设计:

    分别用 StringBuilder 和 StringBuffer 将一指定的字符串自连接一百万次,比较两种方法所用的时间。为尽量避免环境的干扰,测试时会关闭本机中其它应用程序,并且为了避免测试组之间的相互干扰,在每组测试完成后会重起机器。每个程序运行十次,最后取平均值。

测试环境:CPU: Celeron – M420
RAM: 1G
OS: Window XP Home Edition
JDK: Sun JDK 1.6.0 (Java HotSpot™ Client VM (build 1.6.0-b105, mixed mode, sharing))
运行程序时没有为 JVM 指定任何参数,全部使用默认值
程序段:

1.  用 StringBuffer

  1. private static final int COUNT = 1000000;  
  2. private static final String TEMPLATE = "0123456789" ;  
  3. public static void useStringBuffer() {  
  4.    StringBuffer bf = new StringBuffer( "" );  
  5.    String target = null ;  
  6.    long start = System.currentTimeMillis();  
  7.    for ( int i = 0; i < COUNT ; i++) {  
  8.        bf.append( TEMPLATE );  
  9.    }  
  10.    target = bf.toString();  
  11.    long end = System.currentTimeMillis();  
  12.    System. out .println( "Use StringBuffer, time is " + (end - start));  
  13. }     

 
  1. private static final int COUNT = 1000000;  
  2. private static final String TEMPLATE = "0123456789" ;  
  3. public static void useStringBuffer() {  
  4.    StringBuffer bf = new StringBuffer( "" );  
  5.    String target = null ;  
  6.    long start = System.currentTimeMillis();  
  7.    for ( int i = 0; i < COUNT ; i++) {  
  8.        bf.append( TEMPLATE );  
  9.    }  
  10.    target = bf.toString();  
  11.    long end = System.currentTimeMillis();  
  12.    System. out .println( "Use StringBuffer, time is " + (end - start));  
  13. }     
2.  用 StringBuilder

  private static final int COUNT = 1000000;

 
  1. private static final String TEMPLATE = "0123456789" ;  
  2. public static void useStringBuilder() {  
  3.    StringBuilder bf = new StringBuilder( "" );  
  4.    String target = null ;  
  5.    long start = System.currentTimeMillis();  
  6.    for ( int i = 0; i < COUNT ; i++) {  
  7.        bf.append( TEMPLATE );  
  8.    }  
  9.    target = bf.toString();  
  10.    long end = System.currentTimeMillis();  
  11.    System. out .println( "Use StringBuilder, time is " + (end - start));  
  12. }  

 
  1. private static final String TEMPLATE = "0123456789" ;  
  2. public static void useStringBuilder() {  
  3.    StringBuilder bf = new StringBuilder( "" );  
  4.    String target = null ;  
  5.    long start = System.currentTimeMillis();  
  6.    for ( int i = 0; i < COUNT ; i++) {  
  7.        bf.append( TEMPLATE );  
  8.    }  
  9.    target = bf.toString();  
  10.    long end = System.currentTimeMillis();  
  11.    System. out .println( "Use StringBuilder, time is " + (end - start));  
  12. }  
测试结果:

No.StringBufferStringBuilder
1328328
2344312
3328328
4344312
5344328
6344312
7328328
8344312
9343328
10344328
平均值339.1321.6

 从结果中可以看出两者的性能差异约为 5.44 %

下面我们将对测试程序做一点点小小的改动,在 new 一个新的 StringBuffer/StringBuilder 时,我们指定一个容量参数。修改的代码如下:

 1.  用 StringBuffer

  1. private static final String TEMPLATE = "0123456789" ;  
  2. private static final int COUNT = 1000000;  
  3. public static void useStringBuffer() {  
  4.    StringBuffer bf = new StringBuffer(COUNT * TEMPLATE.length());  
  5.    String target = null ;  
  6.    long start = System.currentTimeMillis();  
  7.    for ( int i = 0; i < COUNT ; i++) {  
  8.        bf.append( TEMPLATE );  
  9.    }  
  10.    target = bf.toString();  
  11.    long end = System.currentTimeMillis();  
  12.    System. out .println( "Use StringBuffer, time is " + (end - start));  
  13. }     

 
  1. private static final String TEMPLATE = "0123456789" ;  
  2. private static final int COUNT = 1000000;  
  3. public static void useStringBuffer() {  
  4.    StringBuffer bf = new StringBuffer(COUNT * TEMPLATE.length());  
  5.    String target = null ;  
  6.    long start = System.currentTimeMillis();  
  7.    for ( int i = 0; i < COUNT ; i++) {  
  8.        bf.append( TEMPLATE );  
  9.    }  
  10.    target = bf.toString();  
  11.    long end = System.currentTimeMillis();  
  12.    System. out .println( "Use StringBuffer, time is " + (end - start));  
  13. }     
2. 用 StringBuilder
  1. private static final String TEMPLATE = "0123456789" ;  
  2.   private static final int COUNT = 1000000;  
  3.   public static void useStringBuilder() {  
  4.      StringBuilder bf = new StringBuilder(COUNT * TEMPLATE.length());  
  5.      String target = null ;  
  6.      long start = System.currentTimeMillis();  
  7.      for ( int i = 0; i < COUNT ; i++) {  
  8.          bf.append( TEMPLATE );  
  9.      }  
  10.      target = bf.toString();  
  11.      long end = System.currentTimeMillis();  
  12.      System. out .println( "Use StringBuilder, time is " + (end - start));  
  13.   }   

 
  1. private static final String TEMPLATE = "0123456789" ;  
  2.   private static final int COUNT = 1000000;  
  3.   public static void useStringBuilder() {  
  4.      StringBuilder bf = new StringBuilder(COUNT * TEMPLATE.length());  
  5.      String target = null ;  
  6.      long start = System.currentTimeMillis();  
  7.      for ( int i = 0; i < COUNT ; i++) {  
  8.          bf.append( TEMPLATE );  
  9.      }  
  10.      target = bf.toString();  
  11.      long end = System.currentTimeMillis();  
  12.      System. out .println( "Use StringBuilder, time is " + (end - start));  
  13.   }   

测试结果:(表格中第一,二组为上一轮测试的结果) 

No.StringBufferStringBuilderStringBuffer(int)StringBuilder(int)
132832814094
2344312125125
332832812593
4344312125125
534432810994
6344312125110
7328328125110
8344312110110
9343328140109
10344328109125
平均值339.1321.6123.3109.5

    从表中可以看到 StringBuffer(int) 和 StringBuilder(int) 两者之间的差异为 12.6% 。但我们更应该看到采用不同的构造方法所带来的性能提升, StringBuffer 提升了 175.02 %, StringBuilder 提升了 193.70% 。原因在于不指定 StirngBuffer/StringBuilder 的容量时,它们内部的字符缓冲区为 16 个字符(无参构造)或字符串参数的长度,当程序不断的进行 append/insert 操作时,每当字符数超过原有的容量后, StringBuffer/StringBuilder 将不断的进行自动扩展的工作,这将消耗比较多的时间。

    也许有人会说这样的测试并不能反映真实的情况,因为在实际的开发中很少会在一个方法中构造 / 拼接一个长度为 10*1000000 的字符串的。更通常的情况是在一个方法中构造一个不太长的串,但该方法将被大量的,反复的调用。 OK, 我们可以修改一下测试程序来放映这种情况。

    新程序中 contactWith…. 方法用来拼接一个不太长的字符串,该方法被 use…. 方法反复调用十万次,并记录总的调用时间。程序如下:

1.  使用 StringBuffer

  1. private static final String TEMPLATE = "0123456789" ;  
  2. private static final int COUNT = 100000;  
  3. private static final int COUNT2 = 10;  
  4. public static String contactWithStringBuffer() {  
  5. //     StringBuffer bf = new StringBuffer("");  
  6.    StringBuffer bf = new StringBuffer( COUNT2 * TEMPLATE .length());  
  7.    for ( int i = 0; i < COUNT2 ; i++) {  
  8.        bf.append( TEMPLATE );  
  9.    }  
  10.    return bf.toString();  
  11. }  
  12.   
  13. public static void useStringBuffer() {  
  14.    long start = System.currentTimeMillis();  
  15.    for ( int i = 0; i < COUNT ; i++) {  
  16.        contactWithStringBuffer();  
  17.    }  
  18.    long end = System.currentTimeMillis();  
  19.    System. out .println( "Use StringBuffer, Time is " + (end - start));  

 
  1. private static final String TEMPLATE = "0123456789" ;  
  2. private static final int COUNT = 100000;  
  3. private static final int COUNT2 = 10;  
  4. public static String contactWithStringBuffer() {  
  5. //     StringBuffer bf = new StringBuffer("");  
  6.    StringBuffer bf = new StringBuffer( COUNT2 * TEMPLATE .length());  
  7.    for ( int i = 0; i < COUNT2 ; i++) {  
  8.        bf.append( TEMPLATE );  
  9.    }  
  10.    return bf.toString();  
  11. }  
  12.   
  13. public static void useStringBuffer() {  
  14.    long start = System.currentTimeMillis();  
  15.    for ( int i = 0; i < COUNT ; i++) {  
  16.        contactWithStringBuffer();  
  17.    }  
  18.    long end = System.currentTimeMillis();  
  19.    System. out .println( "Use StringBuffer, Time is " + (end - start));  

2.  使用 StringBuilder

  1. private static final String TEMPLATE = "0123456789" ;  
  2.     private static final int COUNT = 100000;  
  3.     private static final int COUNT2 = 10;  
  4.     public static String contactWithStringBuilder() {  
  5. //     StringBuilder bf = new StringBuilder("");  
  6.        StringBuilder bf = new StringBuilder( COUNT2 * TEMPLATE .length());  
  7.        for ( int i = 0; i < COUNT2 ; i++) {  
  8.            bf.append( TEMPLATE );  
  9.        }  
  10.        return bf.toString();  
  11.     }  
  12.      
  13.     public static void useStringBuilder() {  
  14.        long start = System.currentTimeMillis();  
  15.        for ( int i = 0; i < COUNT ; i++) {  
  16.            contactWithStringBuilder();  
  17.        }  
  18.        long end = System.currentTimeMillis();  
  19.        System. out .println( "Use StringBuilder, Time is " + (end - start));  
  20.     }   }   

 

  1. private static final String TEMPLATE = "0123456789" ;  
  2.     private static final int COUNT = 100000;  
  3.     private static final int COUNT2 = 10;  
  4.     public static String contactWithStringBuilder() {  
  5. //     StringBuilder bf = new StringBuilder("");  
  6.        StringBuilder bf = new StringBuilder( COUNT2 * TEMPLATE .length());  
  7.        for ( int i = 0; i < COUNT2 ; i++) {  
  8.            bf.append( TEMPLATE );  
  9.        }  
  10.        return bf.toString();  
  11.     }  
  12.      
  13.     public static void useStringBuilder() {  
  14.        long start = System.currentTimeMillis();  
  15.        for ( int i = 0; i < COUNT ; i++) {  
  16.            contactWithStringBuilder();  
  17.        }  
  18.        long end = System.currentTimeMillis();  
  19.        System. out .println( "Use StringBuilder, Time is " + (end - start));  
  20.     }   }   
  测试结果: 

No.StringBufferStringBuilderStringBuffer(int)StringBuilder(int)
1188156140109
2187172141125
3188172125110
4188172141110
5187172125110
6188172125109
7172172125125
8188157125110
9203172125110
10188172125109
平均值187.7168.9129.7112.7

     在这种情况下, StringBuffer 与 StringBuilder 的性能差别为: 11.13% 和 15.08% (使用 int 构造函数);而用不同的构造函数的性能差差异分别达到: 44.71% ( StringBuffer )和 49.87% ( StringBuilder )。并且为 StringBuffer 指定容量(使用 StirngBuffer(int) )比不指定容量的 StringBuilder 的性能高出 30.22% 。

 结论:

1.  为了获得更好的性能,在构造 StirngBuffer 或 StirngBuilder 时应尽可能指定它的容量。当然,如果你操作的字符串长度不超过 16 个字符就不用了。

2.  相同情况下使用 StirngBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。而在现实的模块化编程中,负责某一模块的程序员不一定能清晰地判断该模块是否会放入多线程的环境中运行,因此:除非你能确定你的系统的瓶颈是在 StringBuffer 上,并且确定你的模块不会运行在多线程模式下,否则还是用 StringBuffer 吧 J

3.  用好现有的类比引入新的类更重要。很多程序员在使用 StringBuffer 时是不指定其容量的(至少我见到的情况是这样),如果这样的习惯带入 StringBuilder 的使用中,你将只能获得 10 %左右的性能提升(不要忘了,你可要冒多线程的风险噢);但如果你使用指定容量的 StringBuffer ,你将马上获得 45% 左右的性能提升,甚至比不使用指定容量的 StirngBuilder 都快 30% 左右。

特别声明:

1 .本人是基于 Window XP 环境,用 Sun 的 JDK 1.6 完成的以上测试。测试的结果是否能反映其它操作系统(如 Linux, Unix 等)和不同的 JDK (IBM, Weblogic 等 ) 的情况就不得而知,有兴趣的网友可以在不同的环境中测试

 

转自:http://blog.csdn.net/zeo112140/article/details/7176695

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值