字符串相加并不慢

标签:Python, 性能, JavaScript, Java

在学Java时,我对拼接字符串有个很深刻的印象:StringBuilder.append()比String相加要快很多。
这个偏见影响了我几年,直到今天才发现它并不一定适用于其他语言。

先来看看Java的版本:
public class Test {
	private static void f() {
		long d = System.currentTimeMillis();
		for (int i = 0; i < 100; ++i) {
			String s = "";
			for (int j = 0; j < 1000; ++j) {
				s += "1234567890";
			}
		}
		System.out.println(System.currentTimeMillis() - d);
	}

	private static void g() {
		long d = System.currentTimeMillis();
		for (int i = 0; i < 10000; ++i) {
			StringBuilder sb = new StringBuilder();
			for (int j = 0; j < 1000; ++j) {
				sb.append("1234567890");
			}
			String s = sb.toString();
		}
		System.out.println(System.currentTimeMillis() - d);
	}

	public static void main(String[] args) {
		f();
		g();
	}
}
注意因为String相加太慢,所以循环的执行次数只有StringBuilder的1%。
最终测试结果分别是610和640,可见StringBuilder要快2个数量级。

接着看看JavaScript(在Chrome上运行):
function f() {
	var d = new Date();
	for (var i = 0; i < 10000; ++i) {
		var s = '';
		for (var j = 0; j < 1000; ++j) {
			s += '1234567890';
		}
	}
	console.log(new Date() - d);
}

function g() {
	var d = new Date();
	for (var i = 0; i < 10000; ++i) {
		var a = [];
		for (var j = 0; j < 1000; ++j) {
			a.push('1234567890');
		}
		var s = a.join();
	}
	console.log(new Date() - d);
}

f();
g();
结果分别是147和203,字符串相加逆转了。值得一提的是,速度居然比Java还快。

最后看Python:
from timeit import Timer
from io import BytesIO


def f():
	s = ''
	for i in xrange(1000):
		s += '1234567890'

def g():
	a = []
	for i in xrange(1000):
		a.append('1234567890')
	s = ''.join(a)

def h():
	b = BytesIO()
	for i in xrange(1000):
		b.write('1234567890')
	s = b.getvalue()

print Timer('f()', 'from __main__ import f').timeit(10000)
print Timer('g()', 'from __main__ import g').timeit(10000)
print Timer('h()', 'from __main__ import h').timeit(10000)
成绩分别是2.17029650416、2.00979007108和2.48308178833,字符串略慢于数组,但快于BytesIO。

不得不说这个测试结果让我凌乱了,难道是Java的String太笨重了么?

24条评论 你不来一发么↓ 顺序排列 倒序排列

    向下滚动可载入更多评论,或者点这里禁止自动加载

    想说点什么呢?