2013-09-21 63 views
1

我一直在考慮一個字符串:最有效的方法來實現這個?

00122334455667788990875645346787659870984780... 

上面給出的字符串大小將始終是偶數。 我必須實現一個方法,它將返回一個字符串的Arraylist,其中每個元素將包含2個字符。例如,對於上面的字符串:

1st position of arraylist will contain: 00 
2nd: 12 
3rd: 23 
... 

我試圖實現它自己,這是我的功能看起來像:

private static ArrayList<String> getArrayListFrom(String data) { 
    if(data.length()%2==0){ 
     ArrayList<String> aList = new ArrayList<String>(); 
     char[] dArray = data.toCharArray(); 
     //logic here. 
     for(int i = 0; i < dArray.length + 2; i = i+2){ 
      if(i != 0){ 
       aList.add(dArray[i-2]+""+dArray[i-1]); 
      } 
     } 
     return aList; 
    }else{ 
     System.out.println("Invalid data."); 
     return null; 
    } 
} 

This URL表明,簡單的迭代在這種情況下更有效。你們同意嗎?

+0

什麼是您的效率標準?性能?簡明? – assylias

+0

它應該能夠儘快處理這樣的大字符串。 :-) – dreamer

回答

10

你可以用一個單一的分裂做到這一點(當然,這可能不是最有效的運行,但這是簡潔,較小的代碼編寫):

String[] arr = str.split("(?<=\\G..)"); 

,然後用Arrays#asList()方法得到List<String>

正則表達式模式在前面有2個字符的空白處分開 - ..,但忽略之前匹配中已考慮的字符 - \\G。主播\\G匹配前一場比賽結束的位置。

String str = "00122334455667788990875645346787659870984780"; 
String[] arr = str.split("(?<=\\G..)"); 

System.out.println(Arrays.asList(arr)); 

打印:

[00, 12, 23, 34, 45, 56, 67, 78, 89, 90, 87, 56, 45, 34, 67, 87, 65, 98, 70, 98, 47, 80] 

這裏是如何拆分您的字符串進行:

" 00  1 2  2334455667788990875645346787659870984780" (whitespaces represent empty string) 
//  |  |  | 
// split, no-split, split -> gives 12 
// | | |  | 
// \ /\ /
// gives 00 as the preceding two characters are `1` and `0`. 
//   but 0 is already considered for the previous empty string 

參考:


如果運行時性能是一個問題,那麼你就可以用簡單的循環去:

String str = "00122334455667788990875645346787659870984780"; 
List<String> list = new ArrayList<String>(); 
for (int i = 0; i < str.length(); i += 2) { 
    list.add(str.substring(i, i + 2)); 
} 
System.out.println(list); 

但是你可以自己查一下,正則表達式拆分是否是真的大型字符串的性能瓶頸,並且適當地對它們進行基準測試。


我測試了兩種方法 - 分割和循環。正如所期望的,循環比分割字符串長度幾乎高4-5倍,例如1000。在幾個連續運行

public static void usingSplit(String str) { 
    String[] arr = str.split("(?<=\\G..)"); 
    List<String> list = Arrays.asList(arr); 
} 

public static void usingLoop(String str) { 
    List<String> list = new ArrayList<String>(); 
    for (int i = 0; i < str.length(); i += 2) { 
     list.add(str.substring(i, i + 2)); 
    } 
} 

// Warm up JVM 
    for (int i = 0; i < 1000000; ++i) { 
     usingSplit(str); 
    } 
    for (int j = 0; j < 1000000; j++) { 
     usingLoop(str); 
    } 

    long nano = System.nanoTime(); 
    for (int i = 0; i < 1000000; ++i) { 
     usingSplit(str); 
    } 
    System.out.println("Time with usingSplit(): " + (System.nanoTime() - nano) * 1.0/Math.pow(10, 9) + " Seconds"); 

    nano = System.nanoTime(); 
    for (int j = 0; j < 1000000; j++) { 
     usingLoop(str); 
    } 
    System.out.println("Time with usingLoop(): " + (System.nanoTime() - nano) * 1.0/Math.pow(10, 9) + " Seconds"); 

輸出:

Run 1: 
Time with usingSplit(): 34.391315143 Seconds 
Time with usingLoop(): 7.515221612 Seconds 

Run 2: 
Time with usingSplit(): 33.41518869 Seconds 
Time with usingLoop(): 7.868896218 Seconds 

如果有人認爲該基準測試結果是有缺陷的,那麼請記下它的意見。

+0

正則表達式被解釋,效率低下。 –

+0

@AlexeiKaigorodov。那麼,有時候一個任務真的要用正則表達式完成。迭代字符串也是一種選擇。但是,您只需使用拆分編寫較少的代碼。而且它並沒有像你所假設的那麼低效。 –

+0

@RohitJain(謙虛)我提到了一個網址,這表明在某些情況下簡單的迭代更有效率。你怎麼看 ? – dreamer

6
ArrayList<String> aList = new ArrayList<String>(); 
    //logic here. 
    for(int i = 0; i < data.length(); i+=2){ 
     aList.add(data.subString(i, i+2)); 
    } 
    return aList; 
+2

爲了獲得更好的性能,特別是如果字符串很長,請事先調整列表的大小:'new ArrayList <>(data.length/2);' – assylias

+1

由於OP說他/她正在使用J2ME,所以可能使用Vector。 – bsd

+0

@bsd我將首先嚐試使用Vector實現它。 – dreamer