java 字符串连接(+、concat、StringBuffer/StringBuilder)效率比对

2023-05-16

三种方法

java字符串连接有三种方法:

  1. 用加号+连接,如:"abc"+"bcd"
  2. String对象的concat方法,如:"abc".concat("bcd")
  3. 以及StringBuffer或StringBuilder类,如:
	StringBuilder stringBuilder = new StringBuilder ("abc");
	stringBuilder.append ("bcd");
	stringBuilder.toString ();

StringBuffer和StringBuilder都是继承于AbstractStringBuilder的,这两个类在API和对AbstractStringBuilder的实现都是非常相似的。最主要的区别还是在于StringBuffer使用了synchronized来保证线程安全,而StringBuilder则不适用于多线程环境。

效率对比

用来测试的代码:

		long startTime = System.currentTimeMillis ();

		String str = "";
		StringBuilder stringBuilder = new StringBuilder ();
		for (int i = 0; i < 500000; i++) {
//			str = str.concat ("a ");
//			str += "a ";
			stringBuilder.append ("a ");
		}
		str = stringBuilder.toString ();

		long elapsedMillis = System.currentTimeMillis () - startTime;
		System.out.println ("elapsedMillis=" + elapsedMillis);

经过反复测试之后三种方法的效率对比:

StringBuilder >> concat > +

可以看出在如上的测试代码上,StringBuilder的效率远超其他两种。

但是,并不能说明在任何情况下,StringBuilder的效率都绝对超过加号和concat,具体原因且看下面的分析。

源码分析

String类内部是维护了一个char[]字符数组的,字符串拼接的本质就是创建一个可以容纳下两个旧char[]的新char[],再将两个String内部的char[]数组分别copy过去,数组copy肯定最后用的都是System.arraycopy。

既然原理都是一样的,那为什么上面的测试中StringBuilder的性能要明显优于其他两种方法呢?并且java规范中明确说了,加号就是用StringBuffer或StringBuilder实现的。

原因就在于创建char[]对象的个数不同。

concat方法

每调用一次concat就会创建一个新String,新String内部char[]长度正好等于两个旧String的长度之和,循环50W次就要创建50W个char[]!

StringBuffer和StringBuilder

StringBuffer和StringBuilder则不一样,它们内部维护了一个可变长的数组。

可变长并不是指这个数组对象长度可变,数组对象一经创建长度就是固定的。可变长的数组实际上是指这个数组引用没被final修饰符修饰,可以让它指向长度更长的数组对象,这个过程叫扩容。String 内部数组不可变长的原因是用了final修饰。

数组的初始容量是大于你传入的字符串的长度的(多16),每次append就是将String的char[] copy到StringBuffer和StringBuilder的内部数组里面。空间不够用了就会进行扩容, 每次扩容新容量 = 旧容量 x 2 + 2,这样就可以大大减少扩容次数,即减少创建数组的数量。这就是在大量数据的情况下StringBuilder效率远超concat的原因。

但是如果仅仅是两个字符串进行拼接的话,concat可能效率更高。

加号

至于加号,每一句str += "a ";会在编译期间被替换成:

 str = new StringBuilder (str).append("a");

"a"+"a"+"a"被替换成:

new StringBuilder (str).append("a").append("a").append("a");

也就是每一句包含加号的语句都会new一个StringBuilder,加号用append替换。

对应到上面的测试程序,每循环一次就会创建一个StringBuilder 对象,效率自然不高。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java 字符串连接(+、concat、StringBuffer/StringBuilder)效率比对 的相关文章

随机推荐