String连接的简单性能测试

/**

* 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差别颇大。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值