java的String字串拼接和StringBuffer的append的速度差異
阿新 • • 發佈:2019-02-09
今天在leetcode上做題的時候發現,實現字串拼接的時候,用StringBuffer的append比String的+快很多。思考了一下這兩者的差別。
我是初學者,有說錯的還請大家指正!
首先得出String的+拼接的時間
public static void main(String[] args) { String str = ""; String s = "abcd"; long starttime = System.currentTimeMillis(); for(int i = 0; i < 100000; i++) { str += s; } long stoptime = System.currentTimeMillis(); System.out.println(stoptime - starttime); }
執行程式三次,得到的結果為14726ms、14788ms、14930ms
姑且認為完成100000次拼接的時間為14800ms。
並且,在實驗中發現,如果完成10000次拼接(十分之一規模)的時間是200ms左右,遠小於上面時間的十分之一。
下面測試StringBuffer的append所用的時間
執行程式三次,得到的結果為16ms、15ms、15mspublic static void main(String[] args) { StringBuffer str = new StringBuffer(); StringBuffer s = new StringBuffer("abcd"); long starttime = System.currentTimeMillis(); for(int i = 0; i < 100000; i++) { str.append(s); } long stoptime = System.currentTimeMillis(); System.out.println(stoptime - starttime); }
姑且認為完成100000次append的時間為15ms。
同時發現,append的時間複雜度似乎是N。這一點不太確定。
由上可見用StringBuffer的append來完成 “字串拼接“ 比String的拼接快很多,特別是在量大的情況下。
但是這是為什麼呢?
因為String是字串常量,而StringBuffer是變數。
也就是說String型的資料,一旦被建立是不可修改的,對其進行修改的話,會另外建立一個新的String,然後把資料複製過去,舊的就當垃圾處理掉了。這樣一來,效率就及其低下了。
那麼StringBuffer是怎麼做的呢?我發現了這麼一段原始碼:
/**
* Appends the specified string to this character sequence.
* <p>
* The characters of the {@code String} argument are appended, in
* order, increasing the length of this sequence by the length of the
* argument. If {@code str} is {@code null}, then the four
* characters {@code "null"} are appended.
* <p>
* Let <i>n</i> be the length of this character sequence just prior to
* execution of the {@code append} method. Then the character at
* index <i>k</i> in the new character sequence is equal to the character
* at index <i>k</i> in the old character sequence, if <i>k</i> is less
* than <i>n</i>; otherwise, it is equal to the character at index
* <i>k-n</i> in the argument {@code str}.
*
* @param str a string.
* @return a reference to this object.
*/
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
// Documentation in subclasses because of synchro difference
public AbstractStringBuilder append(StringBuffer sb) {
if (sb == null)
return appendNull();
int len = sb.length();
ensureCapacityInternal(count + len);
sb.getChars(0, len, value, count);
count += len;
return this;
}
粗略地看了一下程式碼,大概是StringBuffer型的資料的大小是可變的,在append時先增大其記憶體,然後利用getChars()將被append的資料複製過去。。快就快在不用每一次都重新建立變數,每次複製的內容較少吧。。
另外,聽說StringBuilder的效果更好。先留個坑,以後碰到了再研究。