在最初寫java代碼時,在字符串的使用上,通常常量定義為String,變量定義為StringBuffer,基本不用StringBuilder,下面轉載一篇博客記錄一下StringBuffer和StringBuilder的區別,原帖地址:http://blog.csdn.net/mad1989/article/details/26389541
StringBuffer、StringBuilder和String一樣,也用來代表字符串。String類是不可變類,任何對String的改變都會引發新的String對象的生成;StringBuffer則是可變類,任何對它所指代的字符串的改變都不會產生新的對象。既然可變和不可變都有了,為何還有一個StringBuilder呢?相信初期的你(你說的對,我就是在初期),在進行append時,一般都會選擇StringBuffer吧!
先說一下集合的故事,HashTable是線程安全的,很多方法都是synchronized方法,而HashMap不是線程安全的,但其在單線程程序中的性能比HashTable要高。StringBuffer和StringBuilder類的區別也是如此,他們的原理和操作基本相同,區別在于StringBufferd支持并發操作,線性安全的,適 合多線程中使用。StringBuilder不支持并發操作,線性不安全的,不適合多線程中使用。新引入的StringBuilder類不是線程安全的,但其在單線程中的性能比StringBuffer高。
這里筆者補充一點,HashTable是遠古版本JDK就包含的類,如果沒記錯的話,HashTable相比HashMap少了很多常用方法,比如沒有獲取key集合的方法,也不支持設置一個空的key。
接下來,我直接貼上測試過程和結果的代碼,一目了然(這里原帖的代碼沒有import依賴的類,筆者進行了微調):
package string_test;import java.util.ArrayList;import java.util.Iterator;import java.util.List;public class StringTest { public static String BASEINFO = "Mr.Y"; public static final int COUNT = 2000000; /** * 執行一項String賦值測試 */ public static void doStringTest() { String str = new String(BASEINFO); long starttime = System.currentTimeMillis(); for (int i = 0; i < COUNT / 100; i++) { str = str + "miss"; } long endtime = System.currentTimeMillis(); System.out.PRintln((endtime - starttime) + " millis has costed when used String."); } /** * 執行一項StringBuffer賦值測試 */ public static void doStringBufferTest() { StringBuffer sb = new StringBuffer(BASEINFO); long starttime = System.currentTimeMillis(); for (int i = 0; i < COUNT; i++) { sb = sb.append("miss"); } long endtime = System.currentTimeMillis(); System.out.println((endtime - starttime) + " millis has costed when used StringBuffer."); } /** * 執行一項StringBuilder賦值測試 */ public static void doStringBuilderTest() { StringBuilder sb = new StringBuilder(BASEINFO); long starttime = System.currentTimeMillis(); for (int i = 0; i < COUNT; i++) { sb = sb.append("miss"); } long endtime = System.currentTimeMillis(); System.out.println((endtime - starttime) + " millis has costed when used StringBuilder."); } /** * 測試StringBuffer遍歷賦值結果 * * @param mlist */ public static void doStringBufferListTest(List<String> mlist) { StringBuffer sb = new StringBuffer(); long starttime = System.currentTimeMillis(); for (String string : mlist) { sb.append(string); } long endtime = System.currentTimeMillis(); System.out.println(sb.toString() + "buffer cost:" + (endtime - starttime) + " millis"); } /** * 測試StringBuilder迭代賦值結果 * * @param mlist */ public static void doStringBuilderListTest(List<String> mlist) { StringBuilder sb = new StringBuilder(); long starttime = System.currentTimeMillis(); for (Iterator<String> iterator = mlist.iterator(); iterator.hasNext();) { sb.append(iterator.next()); } long endtime = System.currentTimeMillis(); System.out.println(sb.toString() + "builder cost:" + (endtime - starttime) + " millis"); } public static void main(String[] args) { doStringTest(); doStringBufferTest(); doStringBuilderTest(); List<String> list = new ArrayList<String>(); list.add(" I "); list.add(" like "); list.add(" BeiJing "); list.add(" tian "); list.add(" an "); list.add(" men "); list.add(" . "); doStringBufferListTest(list); doStringBuilderListTest(list); }}執行結果如下(這里貼的是筆者機器的執行結果,比原作者的性能稍微好點
):
從上面的結果可以看出,不考慮多線程,采用String對象時(我把Count/100),執行時間比其他兩個都要高(也就是說,如果執行次數一樣的話,String的用時大約會是200000毫秒左右),而采用StringBuffer對象和采用StringBuilder對象的差別也比較明顯。由此可見,如果我們的程序是在單線程下運行,或者是不必考慮到線程同步問題,我們應該優先使用StringBuilder類;如果要保證線程安全,自然是StringBuffer。
新聞熱點
疑難解答