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的效果更好。先留个坑,以后碰到了再研究。

猜你喜欢

转载自blog.csdn.net/sinat_15901371/article/details/77945375