什么情况下用+运算符进行字符串连接比调用StringBuilder对象的append方法连接字符串性能更好?
2017-05-23 18:05
585 查看
经常在网上看到或者在周围听到有人说字符串拼接不要直接用 String 相加, StringBuilder 的效率要比 String 直接相加拼接要高。还有人常说, StringBuffer 是同步的(线程安全的), StringBuilder 不是线程安全的,同步带来了性能消耗,那么 String 、 StringBuilder 、 StringBuffer 这三者的效率到底有多大的差距呢?
Talk is cheap, show me the code!
很简单的代码,通过调整循环次数的大小,来打印出三种字符串连接所花费的时间:
从上面的输出打印我们可以明显地看出,在循环次数次数较小(比如说小于100)时,三者的时间效率差不多,当随着循环次数的增加,对比效果发生了显著的变化。
我们平时用字符串直接相加作连接,也可以,但在循环内部最好还是用 StringBuilder 作字符串的连接,其实在循环次数较小的情况下我们也可以用 String 直接来相加连接,但有时我们根本不能确定循环次数的大小,所以最好还是老老实实的用 StringBuilder 。
为什么 StringBuilder 和 String 直接连接有如此大的性能差异呢,下面我们来分析一下:
编译器最终会把上面的代码编译为类似下面的代码:
当执行 new StringBuilder(result) 时,构造方法 StringBuilder 会复制 result 中的所有字符到新建的 StringBuilder 中。每次循环都需要创建一个 StringBuilder 对象(创建对象时需要耗费时间和内存),随着循环次数的增大, result 字符串就会越来越长,把 result 中的字符复制到新建的 StringBuilder 中花费的时间也就越长,而且 StringBuilder(result).append(str).toString()
会创建一个临时的字符串,随着循环次数的增加,这个操作花费的时间也会越来越长。总之,随着循环变量 i 的增大,每次循环会变得越来越慢。
从上面的输出可以看出当循环次数增大后, StringBuilder 的效率要比 StringBuffer要好一些。
下面是 StringBuilder 和 StringBuffer 两者之间的一个对比:
当循环次数增大到 1000w后,两者才有了明显的差异, StringBuilder 的效率要比 StringBuffer 的要高一些。
Talk is cheap, show me the code!
public class StringCatTest { public static void main(String[] args) { printResult(100); System.out.println("***********************************************"); printResult(1000); System.out.println("***********************************************"); printResult(10000); System.out.println("***********************************************"); printResult(100000); System.out.println("***********************************************"); printResult(1000000); System.out.println("***********************************************"); printResult(10000000); } public static void printResult(long loopCount) { System.out.println("loopCount:" + loopCount); stringCat(loopCount); stringBuilderAppend(loopCount); stringBufferAppend(loopCount); } public static long stringCat(long loopCount) { long beginTime = System.currentTimeMillis(); String str = "hello,world!"; String result = ""; for (int i = 0; i < loopCount; i++) { result += str; } long consumeTime = System.currentTimeMillis()-beginTime; System.out.println("String cat time:" + consumeTime); return consumeTime; } public static long stringBuilderAppend(long loopCount) { long beginTime = System.currentTimeMillis(); String str = "hello, world!"; String result = ""; StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < loopCount; i++) { stringBuilder.append(str); } result = stringBuilder.toString(); long consumeTime = System.currentTimeMillis()-beginTime; System.out.println("StringBuilder append time:" + consumeTime); return consumeTime; } public static long stringBufferAppend(long loopCount) { long beginTime = System.currentTimeMillis(); String str = "hello, world!"; String result = ""; StringBuffer stringBuffer = new StringBuffer(); for (int i = 0; i < loopCount; i++) { stringBuffer.append(str); } result = stringBuffer.toString(); long consumeTime = System.currentTimeMillis()-beginTime; System.out.println("StringBuffer append time:" + consumeTime); return consumeTime; } }
很简单的代码,通过调整循环次数的大小,来打印出三种字符串连接所花费的时间:
从上面的输出打印我们可以明显地看出,在循环次数次数较小(比如说小于100)时,三者的时间效率差不多,当随着循环次数的增加,对比效果发生了显著的变化。
我们平时用字符串直接相加作连接,也可以,但在循环内部最好还是用 StringBuilder 作字符串的连接,其实在循环次数较小的情况下我们也可以用 String 直接来相加连接,但有时我们根本不能确定循环次数的大小,所以最好还是老老实实的用 StringBuilder 。
为什么 StringBuilder 和 String 直接连接有如此大的性能差异呢,下面我们来分析一下:
String str = "hello,world!"; String result = ""; for (int i = 0; i < loopCount; i++) { result += str; }
编译器最终会把上面的代码编译为类似下面的代码:
String str = "hello,world!"; String result = ""; for (int i = 0; i < loopCount; i++) { result = new StringBuilder(result).append(str).toString(); }
当执行 new StringBuilder(result) 时,构造方法 StringBuilder 会复制 result 中的所有字符到新建的 StringBuilder 中。每次循环都需要创建一个 StringBuilder 对象(创建对象时需要耗费时间和内存),随着循环次数的增大, result 字符串就会越来越长,把 result 中的字符复制到新建的 StringBuilder 中花费的时间也就越长,而且 StringBuilder(result).append(str).toString()
会创建一个临时的字符串,随着循环次数的增加,这个操作花费的时间也会越来越长。总之,随着循环变量 i 的增大,每次循环会变得越来越慢。
从上面的输出可以看出当循环次数增大后, StringBuilder 的效率要比 StringBuffer要好一些。
下面是 StringBuilder 和 StringBuffer 两者之间的一个对比:
当循环次数增大到 1000w后,两者才有了明显的差异, StringBuilder 的效率要比 StringBuffer 的要高一些。
相关文章推荐
- 什么情况下用+运算符进行字符串连接比调用StringBuffer/StringBuilder对象的append方法连接字符串性能更好?
- 什么情况下用+运算符进行字符串连接比调用StringBuilder对象的append方法连接字符串性能更好?
- 什么情况下用+运算符进行字符串连接比调用StringBuffer/StringBuilder对象的append方法连接字符串性能更好?
- 什么情况下用“+”运算符进行字符串连接比调用StringBuffer/StringBuilder 对象的append方法连接字符串性能更好?
- 对对象类型和调用方法属性进行存储以提升反射性能
- ASP调用DLL总对象方法与数据库进行连接
- 对对象类型和调用方法属性进行存储以提升反射性能
- 对对象类型和调用方法属性进行存储以提升反射性能
- StringBuffer对象和传统的字符串连接方法性能测试比较
- ASP调用DLL总对象方法与数据库进行连接
- 关于连接字符串用什么方法取出更好
- 解决asp.net Sharepoint无法连接发布自定义字符串处理程序,不能进行输出缓存处理的方法
- Activator.CreateInstance 方法创建对象和Expression Tree创建对象性能的比较(构造函数含多参数的情况)
- 用反射进行方法调用的性能
- 冒泡排序是选择排序的退化版,再就是一组数中求几个最小的数选择什么方法要根据不同情况进行分类
- 动态调用对象的属性和方法——性能和灵活性兼备的方法
- 数组方法解决JS字符串连接性能问题有争议
- 有没有什么方法可以调用字符串变量,使其像一般语句一般执行.
- 写一个方法进行各种属性的更新,而不要每个界面设置改变都改变一个属性。就是点击应用或确定按钮时调用这个更新属性的方法,遍历所有(控制对象属性的)界面控件的状态(值),进行属性修改和刷新。