2010-03-19 46 views
12

我想基準一些代碼。我發送一個字符串消息在套接字上。我想發送100KB,2MB和10MB字符串變量。有沒有簡單的方法來創建這些尺寸的變量?創建特定大小的Java變量(字符串)

目前我正在這樣做。

private static String createDataSize(int msgSize) { 
    String data = "a"; 
    while(data.length() < (msgSize*1024)-6) { 
     data += "a"; 
    } 
    return data; 
} 

但是這需要很長時間。有沒有更好的辦法?

更新: 謝謝,我現在正在這樣做。

/** 
* Creates a message of size @msgSize in KB. 
*/ 
private static String createDataSize(int msgSize) { 
    // Java chars are 2 bytes 
    msgSize = msgSize/2; 
    msgSize = msgSize * 1024; 
    StringBuilder sb = new StringBuilder(msgSize); 
    for (int i=0; i<msgSize; i++) { 
     sb.append('a'); 
    } 
    return sb.toString(); 
    } 
+1

詳細信息:String.length()返回字符串中的字符數。在網絡上佔用多少字節也取決於您使用的編碼。 – meriton 2010-03-19 01:53:14

+1

爲什麼字符不必是2個字節,但只有1個: http://stackoverflow.com/questions/5078314/isnt-the-size-of-character-in-java-2-bytes – 2015-02-12 13:03:26

回答

19

Java char s的大小是2個字節(16位無符號)。所以如果你想要2MB,你需要一百萬字符。您的代碼有兩個明顯的問題:

  1. 反覆調用length()是不必要的。將任何字符添加到Java String並且它的長度增加1,而不管字符是什麼。也許你會把它和字節大小混淆起來。這並不意味着;和
  2. 該代碼存在大量內存碎片問題。

爲了進一步解釋(2)中,字符串並置運算符(+)在Java中引起新String要創建因爲Java String s爲不可變的。所以:

String a = "a"; 
a += "b"; 

實際上意味着:

String a = "a"; 
String a = a + "b"; 

這有時混淆前的C++程序員作爲字符串使用C不同的工作++。

因此,您的代碼實際上是爲一百萬條消息分配一百萬個字符串。只保留最後一個。其他垃圾將被清理,但沒有必要。

一個更好的版本是:

private static String createDataSize(int msgSize) { 
    StringBuilder sb = new StringBuilder(msgSize); 
    for (int i=0; i<msgSize; i++) { 
    sb.append('a'); 
    } 
    return sb.toString(); 
} 

的關鍵區別在於:

  1. 一個StringBuilder是可變的所以並不需要每次變化重新分配;和
  2. 在此代碼示例中StringBuilder已預分配到正確的大小。

注:精明可能已經注意到我做:

sb.append('a'); 

而不是:

sb.append("a"); 

當然'a'是單個字符,"a"String。你可以在這種情況下使用。

但是,並不是那麼簡單,因爲它取決於字節是如何編碼的。通常除非你指定它,否則它將使用UTF8,它是可變寬度的字符。因此,100萬字符的大小可能在1MB到4MB之間,具體取決於您最終編碼的大小,而您的問題不包含詳細信息。

如果您需要特定大小的數據並且數據無關緊要,我的建議是簡單地使用正確大小的byte數組。

+0

Java字符串是不可變的,所以每個'+ ='實際上通過複製前一個的全部內容來創建一個新的字符串。 (我認爲你的「巨大的內存碎片問題」是一個斜的參考。) – 2010-03-19 01:48:01

+0

在for循環中,我認爲你的意思是sb.append('a'); 代碼很棒!謝謝。 – 2010-03-19 01:52:38

0

是的,有..使用緩衝字符串對象:

StringBuilder stringB = new StringBuilder(2000000); //for the 2mb one 
String paddingString = "abcdefghijklmnopqrs"; 

while (stringB.length() + paddingString.length() < 2000000) 
stringB.append(paddingString); 

//use it 
stringB.toString() 
28

您可以簡單地創建一個大的字符數組。

char[] data = new char[1000000]; 

如果你需要做一個真正的String對象,你可以:

String str = new String(data); 

不要使用+=在循環中建立字符串。這具有O(n2)的內存和時間使用,因爲String對象是不可變的(所以每次你呼叫+=新的String對象必須作出,複製過程中的舊字符串的全部內容)。

+5

+1是唯一指出他的代碼爲什麼很慢的原因。 – meriton 2010-03-19 01:50:47

18

直接使用char []或構建字符串。

char[] chars = new char[size]; 
Arrays.fill(chars, 'a'); 

String str = new String(chars); 

另請注意,一個char在內部使用兩個字節。字符串通過網線多長時間取決於編碼(字母a應該只是一個字節,儘管如此)。

+2

或者你可以使用'Arrays.fill(chars,'a')'。 :-) – 2010-03-19 01:48:49

+2

謝謝你,你永遠不會停止瞭解豐富的Java API ... – Thilo 2010-03-19 01:50:38