使用 String 拼接:java
static void StringTest() { String str = ""; long begin = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { str += i; } long end = System.currentTimeMillis(); long result = end- begin; System.out.println("String 拼接耗時:" + result); }
使用 StringBuffer 拼接:編程
static void StringBufferTest() { StringBuffer str = new StringBuffer(); long begin = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { str.append(i); } long end = System.currentTimeMillis(); long result = end- begin; System.out.println("StringBuffer 拼接耗時:" + result); }
使用 StringBilder 拼接:數組
static void StringBuilderTest() { StringBuilder str = new StringBuilder(); long begin = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { str.append(i); } long end = System.currentTimeMillis(); long result = end- begin; System.out.println("StringBuilder 拼接耗時:" + result); }
上面的代碼,同一電腦執行結果是(單位爲:Millis):安全
String 拼接耗時:23051 StringBuffer 拼接耗時:4 StringBuilder 拼接耗時:3
接下來找下他們的效率快慢的緣由。併發
String 是不可擴展的字符串變量app
String str = "ABCD"; str += "加點東西";
咱們都知道 String 是不可擴展的字符串變量(內存地址不會變,建立了以後,該常量就不會改變了),當編譯器執行 String str = "ABCD";
的時候,內存的方法區中會分配一個空間給常量 "ABCD"
, 棧中的變量 str
指向常量 "ABCD"
的內存地址,這時候完成 String str = "ABCD";
這行代碼。ui
這時候若是咱們對 str
進行拼接操做,即執行 str += "加點東西";
, 那麼編譯器首先會在方法區的常量池尋找有沒有 "ABCD加點東西"
這個字符串常量(這時候確定是沒有該常量)。那麼編譯器會在常量池中從新開闢一塊空間給 "ABCD加點東西"
(可是其實這個步驟,在底層實現的時候也是每次循環都會 StringBuilder對象,並調用其中的 append 方法進行拼接, 這也印證了爲何會 String 比 StringBuilder 效率低),棧中的 str
變量指向 "ABCD加點東西"
的內存地址,完成一次拼接。spa
StringBuffer 和 StringBuilder 都是可擴展的字符串類型。code
StringBuilder sb = new StringBuilder("ABCD"); sb.append("加點東西"); // 或者如下 StringBuffer sb = new StringBuffer("ABCD"); sb.append("加點東西");
StringBuffer 和 StringBuilder 的內部數組 默認長度 = 初始化字符串長度 + 16
。因此當 new StringBuilder("ABCD");
執行完 new 以後,實際上在 sb 中的 capacity() 的返回值是 20
。 這時候會在堆區建立一個 StringBuffer 或者 StringBuilder 對象
,同時會到方法去的產量池中尋找是否有 "ABCD"
這個常量,而後 StringBuffer 或者 StringBuilder 對象
指向常量池的 "ABCD"
這個常量。對象
當執行 sb.append("加點東西");
這行代碼的時候,編譯器就會去常量池找是否有 "ABCD加點東西"
常量,若是沒有那麼就看 StringBuffer 或者 StringBuilder 對象
的長度能都裝載下 "加點東西"
該字符串(若是不夠那麼就增長到當前長度的 150%)。此時的內存地址是不變的。
String
的每次拼接都要在內存中從新分配一塊內存空間,StringBuffer 或者 StringBuilder
的效率天然而言要給 String
的拼接速度要快。StringBuffer 和 StringBuilder
效率差很少,那麼爲啥還要兩個?其中有什麼區別呢?StringBuffer
比 StringBuilder
的實現方法前多了一個 synchronized
,也就是同步鎖,這樣會使 StringBuffer
在併發編程中更加安全,可靠。StringBuilder
在平常開發中是最多見,也是效率最高的。
StringBuilder > StringBuffer > String
StringBuilder
。