String连接的简单性能测试

来源:互联网 发布:python 画图 编辑:程序博客网 时间:2024/05/21 10:28

/**

* String连接性能测试

*@author x1ny

*@date 2015/8/8

*/



根据String 的字节码实现知道 使用 “+”连接字符串实际上是创建了一个StringBuffer对象进行连接操作然后再转换为String对象。下面将在具体测试程序中测试性能的差异。


测试方法:用四种不同的连接方式 创建“tsettesttesttesttest”字符串1千万次,查看其性能差别

测试代码:


public class StringConnectionTest {public static void main(String[] args) {connByOperationOnce(10000000);connByOperation(10000000);connByStringBuffer(10000000);connByStringBuilder(10000000);}public static void connByOperationOnce(int count){long endTime;long time;long startTime = System.currentTimeMillis();String str;for(int i = 0; i <= count; i++)str = "test" + "test" + "test" + "test" + "test";endTime = System.currentTimeMillis();time = endTime - startTime;System.out.println("使用加号一次连接字符串" + count + "次所需要的时间为:" + time + "ms" );}public static void connByOperation(int count){long endTime;long time;long startTime = System.currentTimeMillis();String str;for(int i = 0; i <= count; i++){str = "test";str += "test";str += "test";str += "test";str += "test";}endTime = System.currentTimeMillis();time = endTime - startTime;System.out.println("使用加号多次连接字符串" + count + "次所需要的时间为:" + time + "ms" );}public static void connByStringBuffer(int count){long endTime;long time;long startTime = System.currentTimeMillis();String str;for(int i = 0; i <= count; i++){StringBuffer sb = new StringBuffer("test");sb.append("test");sb.append("test");sb.append("test");sb.append("test");str = sb.toString();}endTime = System.currentTimeMillis();time = endTime - startTime;System.out.println("使用StringBuffer连接字符串" + count + "次所需要的时间为:" + time + "ms" );}public static void connByStringBuilder(int count){long endTime;long time;long startTime = System.currentTimeMillis();String str;for(int i = 0; i <= count; i++){StringBuilder sb = new StringBuilder("test");sb.append("test");sb.append("test");sb.append("test");sb.append("test");str = sb.toString();}endTime = System.currentTimeMillis();time = endTime - startTime;System.out.println("使用StringBuilder连接字符串" + count + "次所需要的时间为:" + time + "ms" );}}

测试结果:


测试版本为1.6.0_65

使用加号一次连接字符串10000000次所需要的时间为:10ms

使用加号多次连接字符串10000000次所需要的时间为:3383ms

使用StringBuffer连接字符串10000000次所需要的时间为:1561ms

使用StringBuilder连接字符串10000000次所需要的时间为:1199ms


测试版本为1.7.0_79

使用加号一次连接字符串10000000次所需要的时间为:6ms

使用加号多次连接字符串10000000次所需要的时间为:2452ms

使用StringBuffer连接字符串10000000次所需要的时间为:2097ms

使用StringBuilder连接字符串10000000次所需要的时间为:864ms


测试版本为1.8.0_40

使用加号一次连接字符串10000000次所需要的时间为:5ms

使用加号多次连接字符串10000000次所需要的时间为:1782ms

使用StringBuffer连接字符串10000000次所需要的时间为:726ms

使用StringBuilder连接字符串10000000次所需要的时间为:840ms


发现使用 String str = "test" + "test" + "test" + "test" + "test" ; 性能与其他方式差距太大,几乎为0,查看字节码可以发现:

     11: ldc           #68                 // String testtesttesttesttest

编译器在编译时直接将语句优化为 String str = "testtesttesttesttest'" 并没有进行连接操作,于是乎花费时间几乎为0。


测试将被连接的字符串“test‘用局部变量保存。


将测试代码改为:


package mytest;public class StringConnectionTest {public static void main(String[] args) {System.out.println("测试版本为" + System.getProperty("java.version"));connByOperationOnce(10000000);connByOperation(10000000);connByStringBuffer(10000000);connByStringBuilder(10000000);}public static void connByOperationOnce(int count){long endTime;long time;String str;String str2 = "test";long startTime = System.currentTimeMillis();for(int i = 0; i <= count; i++)str = str2 + str2 + str2 + str2 + str2;endTime = System.currentTimeMillis();time = endTime - startTime;System.out.println("使用加号一次连接字符串" + count + "次所需要的时间为:" + time + "ms" );}public static void connByOperation(int count){long endTime;long time;String str;String srt2 = "test";long startTime = System.currentTimeMillis();for(int i = 0; i <= count; i++){str = srt2;str += srt2;str += srt2;str += srt2;str += srt2;}endTime = System.currentTimeMillis();time = endTime - startTime;System.out.println("使用加号多次连接字符串" + count + "次所需要的时间为:" + time + "ms" );}public static void connByStringBuffer(int count){long endTime;long time;String str;String str2 = "test";long startTime = System.currentTimeMillis();for(int i = 0; i <= count; i++){StringBuffer sb = new StringBuffer(str2);sb.append(str2);sb.append(str2);sb.append(str2);sb.append(str2);str = sb.toString();}endTime = System.currentTimeMillis();time = endTime - startTime;System.out.println("使用StringBuffer连接字符串" + count + "次所需要的时间为:" + time + "ms" );}public static void connByStringBuilder(int count){long endTime;long time;String str;String str2 = "test";long startTime = System.currentTimeMillis();for(int i = 0; i <= count; i++){StringBuilder sb = new StringBuilder(str2);sb.append(str2);sb.append(str2);sb.append(str2);sb.append(str2);str = sb.toString();}endTime = System.currentTimeMillis();time = endTime - startTime;System.out.println("使用StringBuilder连接字符串" + count + "次所需要的时间为:" + time + "ms" );}}

再进行测试得:

测试版本为1.6.0_65

使用加号一次连接字符串10000000次所需要的时间为:1366ms

使用加号多次连接字符串10000000次所需要的时间为:3433ms

使用StringBuffer连接字符串10000000次所需要的时间为:1449ms

使用StringBuilder连接字符串10000000次所需要的时间为:1139ms


测试版本为1.7.0_79

使用加号一次连接字符串10000000次所需要的时间为:1630ms

使用加号多次连接字符串10000000次所需要的时间为:3432ms

使用StringBuffer连接字符串10000000次所需要的时间为:1512ms

使用StringBuilder连接字符串10000000次所需要的时间为:1152ms


测试版本为1.8.0_40

使用加号一次连接字符串10000000次所需要的时间为:1233ms

使用加号多次连接字符串10000000次所需要的时间为:2780ms

使用StringBuffer连接字符串10000000次所需要的时间为:1175ms

使用StringBuilder连接字符串10000000次所需要的时间为:1085ms



结论:

当在线程不安全的环境下:

应该使用StringBuffer来确保线程安全。


在线程安全的环境下:

使用StringBuilder永远可以获取更高的性能, 但若在一条语句中连接,使用“+”号性能略低但可读性,可维护性更高。


待解决困惑: “+”是使用StringBuilder实现的,在一条语句中使用“+”号连接只创建了一个StringBulider,为什么性能和直接使用StringBulider差别颇大。


0 0
原创粉丝点击