[改善Java代码]自由选择字符串拼接方法
对一个字符串拼接有三种方法:加号,contact方法,StringBuffer或者StringBuilder的append方法,其中加号是最常用的.其他两种方式偶尔会出现在一些开源项目中,那么这三者有什么区别?
//加号拼接
str += "c";
//concat方法连接
str = str.concat("c");
以上是两种不同的字符串拼接方式,循环5万次后再检查执行的时间,加号方式执行的时间是1438毫秒,而concat方法的执行时间是703毫秒,时间相差一倍,如果使用StringBuilder方式,执行时间会更少.
public class Client {
public static final int MAX_LOOP = 50000;
public static void main(String[] args) {
doWithPlus();
doWithConcat();
doWithStringBuffer();
String str ="abc";
String str1 = str.concat("1");
String str2 = "abc1";
System.out.println(str1 == str2);
}
public static void doWithPlus(){
String str = "a";
long start = System.currentTimeMillis();
for(int i=0;i<MAX_LOOP;i++){
str += "c";
//str = new StringBuilder(prefix).append("c").toString();
}
long finish = System.currentTimeMillis();
System.out.println("doWithPlus:" + (finish - start) + "ms");
}
public static void doWithConcat(){
String str = "a";
long start = System.currentTimeMillis();
for(int i=0;i<MAX_LOOP;i++){
str = str.concat("c");
}
long finish = System.currentTimeMillis();
System.out.println("doWithConcat:" + (finish - start) + "ms");
}
public static void doWithStringBuffer(){
StringBuilder sb = new StringBuilder("a");
long start = System.currentTimeMillis();
for(int i=0;i<MAX_LOOP;i++){
sb.append("c");
}
String str = sb.toString();
long finish = System.currentTimeMillis();
System.out.println("doWithStringBuffer:" + (finish - start) + "ms");
}
}
运行结果:
doWithPlus:1559ms
doWithConcat:748ms
doWithStringBuffer:2ms
false
StringBuffer的append方法的执行时间是0毫秒.说明时间非常的短(毫秒不足以计时,可以使用纳秒进行计算).这个实验说明在字符串拼接的方式中,append方法最快,concat方法次之,加号最慢,这是为何呢?
(1)"+"方法拼接字符串
虽然编译器对字符串的加号做了优化,它会使用StringBuilder的append方法进行追加,按道理来说,其执行时间应该也是0毫秒,不过它最终是通过toString方法转换成String字符串的,例子中"+"拼接的代码与如下代码相同:
str = new StringBuilder(str).append("c").toString();
它与纯粹的使用StrignBuilder的append方法是不同的,意思每次循环都会创建一个StringBuilder对象,二是每次执行完毕都要调用toString方法将其转换为字符串------它的时间都耗费在这里了.
(2)concat方法拼接字符串
public String concat(String str) {
int otherLen = str.length();
//如果追加的字符串长度为0,着返回字符串本身
if (otherLen == 0) {
return this;
}
int len = value.length;
char buf[] = Arrays.copyOf(value, len + otherLen);
//追加的字符串转化成字符数组,添加到buf中
str.getChars(buf, len);
//复制字符数组,产生一个新的字符串
return new String(buf, true);
}
其整体看上去就是一个数组的拷贝,虽然在内存中的处理都是原子性操作,速度非常快,不过,注意看最后的return语句,每次的concat操作都会新创建一个String对象,这就是concat速度慢下来的真正原因,它创建了5万个String对象.
(3)append方法拼接字符串
StringBuilder的append方法直接由父类AbstractStringBuilder实现,其代码如下....
public AbstractStringBuilder append(String str) {
if (str == null) str = "null";//如果是null值,则把null作为字符串处理
int len = str.length();
ensureCapacityInternal(count + len);//加长,并作数组拷贝
str.getChars(0, len, value, count);
count += len;
return this;
}
整个append方法都在做字符组处理,加长,然后数组拷贝,这些都是基本数据处理,没有新建任何对象,所以速度也就最快了.
例子中是在最后通过StringBuffer的toString返回了一个字符串,也就是在5万次循环结束之后才生成了一个String对象.
"+"非常符合我们的编码习惯,适合人类阅读,在大多数情况下都可以使用加号操作,只有在系统性能临界的时候才考虑使用concat或者apped方法.
而且很多时候,系统的80%的系能消耗是在20%的代码上,我们的精力应该更多的投入到算法和结构上.
[改善Java代码]自由选择字符串拼接方法的更多相关文章
- [改善Java代码]用枚举实现工厂方法模式更简洁
工厂方法模式(Factory Method Patter)是"创建对象的接口",让子类决定实例化哪一个类,并使一个类的实例化延迟到其子类.工厂方法模式在我们的开发工作中,经常会用到 ...
- [改善Java代码]适时选择getDeclaredxxx和getxxx
Java的Class类提供了很多的getDeclaredxxx方法和getxxx方法,例如getDeclaredmethod和getMethod成对出现,getDeclaredConstructors ...
- [改善Java代码]适时选择不同的线程池来实现
Java的线程池实现从最根本上来说只有两个:ThreadPoolExecutor类和ScheduledThreadPoolExecutor类,这两个类还是父子关系,但是Java为了简化并行计算,还提供 ...
- [改善Java代码]优先选择线程池
在Java1.5之前,实现多线程编程比较麻烦,需要自己启动线程,并关注同步资源,防止线程死锁等问题,在1.5版本之后引入了并行计算框架,大大简化了多线程开发. 我们知道线程有5个状态:新建状态(New ...
- [改善Java代码]推荐覆写toString方法
建议49: 推荐覆写toString方法 为什么要覆写toString方法,这个问题很简单,因为Java提供的默认toString方法不友好,打印出来看不懂,不覆写不行,看这样一段代码: public ...
- [改善Java代码]覆写变长方法也循规蹈矩
建议6:覆写变长方法也循规蹈矩 在Java中,子类覆写父类中的方法很常见,这样做既可以修正Bug也可以提供扩展的业务功能支持,同时还符合开闭原则(Open-Closed Principle),我们来看 ...
- <More Effective C#: 改善C#代码的50个有效方法>中文版翻译答疑
最近, 有一本很赞的.NET技术书中文版出版了 - <More Effective C#: 改善C#代码的50个有效方法>. 从广州\西安\长沙\上海等各地.NET俱乐部都收到反馈, ...
- 【转】使用JavaParser获得Java代码中的类名、方法形参列表中的参数名以及统计总的文件个数与不能解析的文件个数
遍历目录查找Java文件: public static void ergodicDir(File dir, HashSet<String> argNameSet, HashSet<S ...
- [改善Java代码]对字符串排序 持一种宽容的心态
在Java中一涉及到中文处理就会冒出很多的问题来,其中的排序也是一个让人头疼的问题,看代码: import java.util.Arrays; public class Client { public ...
随机推荐
- 第二百七十八天 how can I 坚持
生命的意义.必须要做点什么啊.今年我们二十七八岁. 遇事不急,理清头绪就没那么复杂. 今天突然有点悔意,元旦好像应该不回去看房,花销有点大了,算了,过去的就让他过去吧,都是回忆.至少玩的挺嗨. 记住, ...
- Maven构建Web项目问题汇总
1.Dynamic Web Module 3.0 requires Java 1.6 or newer? 修改pom.xml文件,如下: <build> <plugins> & ...
- C++问题-UniqueAppObject.cpp(147): error C3861: “GUXClientInit”: 找不到标识符
问题经过:在同事的产品上增加新功能,拿来的代码包,用VS打开后,提示某个文件不存在,从项目中移除.CPP.H文件后,提示错误,提示如下:1>UniqueAppObject.cpp(147): e ...
- POJ 1789 Truck History (最小生成树)
Truck History 题目链接: http://acm.hust.edu.cn/vjudge/contest/124434#problem/E Description Advanced Carg ...
- linux sar 命令详解
sar(System Activity Reporter系统活动情况报告)是目前 Linux 上最为全面的系统性能分析工具之一,可以从多方面对系统的活动进行报告,包括:文件的读写情况.系统调用的使用情 ...
- (DP6.1.4.2)POJ 1088 滑雪
其实下面用到的是搜索.(呜呜,DP写的过了测试用例但是却总是AC不了,所以改用搜索来做了) /* * POJ_1088.cpp * * Created on: 2013年10月13日 * Author ...
- java 2 8 10 16
An integer literal may be expressed in decimal (base 10), hexadecimal (base 16), octal (base 8), or ...
- Unity3D之Mecanim动画系统学习笔记(一):认识Mecanim动画系统
Mecanim简介 Mecanim动画系统是Unity3D4.0开始引入的一套全新的动画系统,主要提供了下面4个方面的功能: 针对人形角色提供一套特殊的工作流. 动画重定向的能力,可以非常方便的把动画 ...
- web config数据库连接字符串加密
ASP.NET web.config中,数据库连接字符串的加密与解密 ASP.NET web.config中,数据库连接字符串的加密与解密. 开始--->运行,输入cmd,接着输入以下内容 加密 ...
- Posting data to a HttpHandler greater then ~29MB gives a 404 error
1down votefavorite 1 I am testing a HttpHandler that accepts XML. It works fine when a small amount ...