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

三种方法

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 对象,效率自然不高。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值