关于Java字符串的拼接,你了解多少?

关于Java字符串的拼接,你了解多少?

前景

昨晚开了一个review会,就在循环内部创建String对象的问题展开了激烈的讨论。今早小伙伴们意犹未尽,就字符串的拼接又一次在群里炸开了锅。作为一个有几年工作经验的我来说,在这次的讨论中受益匪浅。

代码中常见的字符串拼接方式

用“+”拼接字符串

String ab = "a" + "b";

输出 : ab

String.format()

String ab = String.format("%s%s","a","b");

输出 : ab

StringBuilder和StringBuffer

StringBuilder sb = new StringBuilder()
sb.append(“a”);
sb.append(“b”);
String ab = sb.toString();

输出 : ab

性能测试

网上对它们的性能普遍认为“+号”性能较差。为了看出效果,时间单位为微秒,纳秒有点太小了。

String a1 = "a";
String b1 = "b";
Thread.sleep(1000);
long start1 = System.nanoTime();
String ab1 = a1 + b1;
long end1 = System.nanoTime();
System.out.println("+号拼接 : " + ((end1 - start1) / 1000) + "ws");     


String a2 = "a";
String b2 = "b";
Thread.sleep(1000);
long start2 = System.nanoTime();
String ab2 = String.format("%s%s", a2, b2);
long end2 = System.nanoTime();
System.out.println("String.format() : " + ((end2 - start2) / 1000)+ "ws");      


String a3 = "a";
String b3 = "b";
Thread.sleep(1000);
long start3 = System.nanoTime();
StringBuilder sb = new StringBuilder();
sb.append(a3);
sb.append(b3);
String ab3 = sb.toString();
long end3 = System.nanoTime();
System.out.println("StringBuilder.append() : "+ ((end3 - start3) / 1000)+ "ws");


输出 : 
+号拼接 : 127ws
String.format() : 46584ws
StringBuilder.append() : 62ws


你可以再试试5以内的字符串拼接。结果差不多。

结果

在2-5个数左右的字符串拼接中“+”号拼接和StringBuilder的耗时相差无几,而String.format()耗时较多

分析

为了进一步了解String,查看到了JDK1.6的源码,String.class开头注释写到

  • The Java language provides special support for the string
  • concatenation operator ( + ), and for conversion of
  • other objects to strings. String concatenation is implemented
  • through the <code>StringBuilder</code>(or <code>StringBuffer</code>)
  • class and its <code>append</code> method.
  • String conversions are implemented through the method
  • <code>toString</code>, defined by <code>Object</code> and
  • inherited by all classes in Java. For additional information on
  • string concatenation and conversion, see Gosling, Joy, and Steele,
  • <i>The Java Language Specification</i>.

这段话的大致意思就是说

java语言提供了字符串串联运算符,和其他对象转换为字符串,字符串连接是底层通过StringBuilder或者StringBuffer来实现的。

这下就明白了为什么“+”号拼接和StringBuilder拼接的耗时相差无几了,但为什么String.format()的耗时相差甚远呢?

public static String format(String format, Object ... args) {
	return new Formatter().format(format, args).toString();
}

public Formatter() {
	init(new StringBuilder(), Locale.getDefault());
}

在上述代码中不难看出底层也是用StringBuilder实现的,这就不能理解了,同样是StringBuilder,为什么相差那么大呢?咱们接着往下看。

 private FormatString[] parse(String s) {
	ArrayList al = new ArrayList();
	Matcher m = fsPattern.matcher(s);
        ...
}

上述代码是在new Formatter().format()方法中找到的,原来内部有正则匹配操作。众所周知,正则匹配是很消费性能的。这下可以解开心中的迷惑了。

结论

  • 就可读性和简洁性而言,数量不多的拼接,“+”号拼接是个很不错的字符串拼接方式。
  • String.format()还没找到适合用他的场景。(也许是需要正则匹配,有的话请告诉我)
  • 循环中StringBuilder和StringBuffer性能更优。

转载于:https://my.oschina.net/xiaozhutefannao/blog/884269

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值