1. 程式人生 > >java的String字串拼接和StringBuffer的append的速度差異

java的String字串拼接和StringBuffer的append的速度差異

今天在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所用的時間

	public 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);
	}
執行程式三次,得到的結果為16ms、15ms、15ms

姑且認為完成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的效果更好。先留個坑,以後碰到了再研究。