主题:【倡议】Java SE 5.0和.NET 2.0擂台赛 -- Highway
String可能是使用最广泛的一种操作了,尤其是在现在Web程序开发中。事实上,Java的String是非常特殊的一种Class,即所有的String Object都是Immutable的。为什么要这样对待String呢?因为Sun想尽可能的榨取一切可能的性能。
为了提高连续拼接String的性能,Java提供了一个类叫StringBuffer。使用它在某些情况下可以成千倍的提高性能。但是Sun还是不够满意,在Java 5.0中,它又提供了一个类叫做StringBuilder。
那么StringBuilder和StringBuffer有什么区别呢?StringBuffer是Thread-safe的,而StringBuilder不是。
那么什么是Thread-safe呢?还记得国内火车内的那种厕所吗?一个人进去,把门一锁,然后开始“方便”。其间不会被外人打扰。完事后开门出来,下一个人才能进去。不会有两个人同时一起“方便”的尴尬局面。这就是Thread-safe.显然Thread-safe有一定的开销,比如关门,上锁,开门等等。在有些情况下,我们不需要这么safe,比如在家里(如果只有你和你老婆),或者你是单身汉,家里根本就没外人。在这种情况下,不用Thread-safe可能会更方便一些,效率会更高。
StringBuilder就是这样的设计思想。在一切可能的情况下使用StringBuilder,最大限度的提高性能。
大家看看下面这段小程序,就会有些感性认识了。
源程序
...... String[] strs = null; strs = this.prepareString(5000); this.stringBufferTest(strs); this.stringBuilderTest(strs); this.stringTest(strs); strs = this.prepareString(20000); this.stringBufferTest(strs); this.stringBuilderTest(strs); //this.stringTest(strs); strs = this.prepareString(100000); this.stringBufferTest(strs); this.stringBuilderTest(strs); //this.stringTest(strs); ...... private String[] prepareString(int number){ System.out.println("String number: " + number); String[] strs = new String[number]; for(int i=0; i<number; i++) strs[i] = "Highway" + i; return strs; } private void stringBuilderTest(String[] input){ long start = System.currentTimeMillis(); StringBuilder sb = new StringBuilder(); for(int i=0; i<input.length; i++) sb.append(input[i]); long time = System.currentTimeMillis()-start; System.out.println("StringBuilder Takes Time: " + time + "ms"); return; } private void stringBufferTest(String[] input){ long start = System.currentTimeMillis(); StringBuffer sb = new StringBuffer(); for(int i=0; i<input.length; i++) sb.append(input[i]); long time = System.currentTimeMillis()-start; System.out.println("StringBuffer Takes Time: " + time+ "ms"); return; } private void stringTest(String[] input){ long start = System.currentTimeMillis(); String sb = ""; for(int i=0; i<input.length; i++) sb = sb + input[i]; long time = System.currentTimeMillis()-start; System.out.println("String Append Takes Time: " + time+ "ms"); return; }
反编译得到的程序,这是Java实际工作的Code.
private String[] prepareString(int number) { System.out.println((new StringBuilder()).append("String number: ").append(number).toString()); String strs[] = new String[number]; for(int i = 0; i < number; i++) strs[i] = (new StringBuilder()).append("Highway").append(i).toString(); return strs; } private void stringBuilderTest(String input[]) { long start = System.currentTimeMillis(); StringBuilder sb = new StringBuilder(); for(int i = 0; i < input.length; i++) sb.append(input[i]); long time = System.currentTimeMillis() - start; System.out.println((new StringBuilder()).append("StringBuilder Takes Time: ").append(time).append("ms").toString()); } private void stringBufferTest(String input[]) { long start = System.currentTimeMillis(); StringBuffer sb = new StringBuffer(); for(int i = 0; i < input.length; i++) sb.append(input[i]); long time = System.currentTimeMillis() - start; System.out.println((new StringBuilder()).append("StringBuffer Takes Time: ").append(time).append("ms").toString()); } private void stringTest(String input[]) { long start = System.currentTimeMillis(); String sb = ""; for(int i = 0; i < input.length; i++) sb = (new StringBuilder()).append(sb).append(input[i]).toString(); long time = System.currentTimeMillis() - start; System.out.println((new StringBuilder()).append("String Append Takes Time: ").append(time).append("ms").toString()); }
由上可见,Java在内部尽可能的在使用StringBuilder
[SIZE=3]测试结果:[/SIZE]
String number: 5000 StringBuffer Takes Time: 15ms StringBuilder Takes Time: 0ms String Append Takes Time: 7281ms String number: 20000 StringBuffer Takes Time: 31ms StringBuilder Takes Time: 16ms String number: 100000 StringBuffer Takes Time: 188ms StringBuilder Takes Time: 156ms
由此可见,StringBuilder 确实是有效果的。最慢的是String直接拼接,效果满上千倍,这是大家应该避免的情况。
那么.NET如何呢?.NET只有一个StringBuilder,没有StringBuffer。这个StringBuilder的Public static变量是Thread-safe的,而instance members却不是。哈哈,有意思吧!!!
将上面Java的程序用.NET写一遍,其运行结果比Java快很多,尤其是赤裸裸的SString拼接(20倍)。这是一个很有趣的问题。希望大家能帮我解释一下为什么!!!
String number: 5000 StringBuilder Takes Time: 0ms String Append Takes Time: 422ms String number: 20000 StringBuilder Takes Time: 15ms String number: 100000 StringBuilder Takes Time: 32ms
C#源程序为:
private String[] prepareString(int number) { System.Console.WriteLine("String number: " + number); String[] strs = new String[number]; for(int i=0; i<number; i++) strs[i] = "Highway" + i; return strs; } private void stringBuilderTest(String[] input) { long start = System.Environment.TickCount; StringBuilder sb = new StringBuilder(); for(int i=0; i<input.Length; i++) sb.Append(input[i]); long time = System.Environment.TickCount - start; System.Console.WriteLine("StringBuilder Takes Time: " + time + "ms"); return; } private void stringTest(String[] input) { long start = System.Environment.TickCount; String sb = ""; for(int i=0; i<input.Length; i++) sb = sb + input[i]; long time = System.Environment.TickCount - start; System.Console.WriteLine("String Append Takes Time: " + time + "ms"); return; }
反编译后为:
private void stringBuilderTest(string[] input) { long num1 = Environment.TickCount; StringBuilder builder1 = new StringBuilder(); for (int num2 = 0; num2 < input.Length; num2++) { builder1.Append(input[num2]); } long num3 = Environment.TickCount - num1; Console.WriteLine("StringBuilder Takes Time: " + num3 + "ms"); } private void stringTest(string[] input) { long num1 = Environment.TickCount; string text1 = ""; for (int num2 = 0; num2 < input.Length; num2++) { text1 = text1 + input[num2]; } long num3 = Environment.TickCount - num1; Console.WriteLine("String Append Takes Time: " + num3 + "ms"); }
- 相关回复 上下关系8
呀.. ppw 字142 2004-10-07 06:49:56
😉如果有人出钱,我一定会有积极性。 Highway 字32 2004-10-06 12:05:47
😄老兵肯定有积蓄 ppw 字22 2004-10-06 14:07:09
😅String, StringBuffer &StringBuilder的玄妙
我对.Net2.0 Beta1下StringBuilder的测试结果 老兵帅客 字7255 2004-10-05 10:17:26
我对Java StringBuffer/StringBuilder的测试结果 老兵帅客 字21245 2004-10-05 09:41:54
其实这种测试波动很大。因为我们没有办法控制GC. Highway 字639 2004-10-05 10:24:24
理论上的确如此 老兵帅客 字282 2004-10-05 10:40:33