2012-07-28 60 views
0

我正在讀取一個文件以供稍後解析。該文件的大小不太可能超過MB,所以在這個階段對我來說這可能不是一個關鍵問題。但出於最佳實踐原因,我想知道什麼時候執行操作的最佳時間。執行操作的最佳時間:循環內或循環後

例子:

使用我從http://www.dzone.com/snippets/java-read-file-string粘貼的方法,我讀緩衝區爲一個字符串。我現在想刪除所有的空格。我的方法是目前這樣的:

private String listRaw; 

public boolean readList(String filePath) throws java.io.IOException { 
    StringBuffer fileData = new StringBuffer(1024); 
    BufferedReader reader = new BufferedReader(
      new FileReader(filePath)); 
    char[] buf = new char[1024]; 
    int numRead=0; 
    while((numRead=reader.read(buf)) != -1){ 
     String readData = String.valueOf(buf, 0, numRead); 
     fileData.append(readData); 
     buf = new char[1024]; 
    } 
    reader.close(); 
    listRaw = fileData.toString().replaceAll("\\s",""); 
    return true; 
} 

所以,我從我保存它的時間字符串中刪除所有空白 - 在它的整體 - 一類變量。

對我來說,這意味着更少的處理,但更多的內存使用。出於最佳實踐原因,我會在readData變量上應用replaceAll()操作時更好嗎,因爲我將它追加到fileData?使用更多的處理,但避免傳遞多餘的空白。

我想這對於一個像我正在工作的小文件幾乎沒有影響,但如果它是一個200MB的日誌文件呢?

這是完全取決於個案還是我有更好的一致意見?


感謝您輸入的每個人。我相信你已經幫助我將自己的思維定向爲編寫Java的正確方向。

我已更新我的代碼,以考慮所提出的要點。包括唐羅比的建議,在某些時候,我可能想保留空間。希望事情現在讀得更好!

private String listRaw; 

public boolean readList(String filePath) throws java.io.IOException { 
    StringBuilder fileData = new StringBuilder(51200); 
    BufferedReader reader = new BufferedReader(new FileReader(filePath)); 
    char[] buf = new char[51200]; 
    boolean spaced = false; 
    while(reader.read(buf) != -1){ 
     for(int i=0;i<buf.length;i++) { 
      char c = buf[i]; 
      if (c != '\t' && c != '\r' && c != '\n') { 
       if (c == ' ') { 
        if (spaced) { 
         continue; 
        } 
        spaced = true; 
       } else { 
        spaced = false; 
       } 

       fileData.append(c); 
      } 
     } 
    } 
    reader.close(); 
    listRaw = fileData.toString().trim(); 
    return true; 
} 
+1

測量它並找出!這樣你就知道哪個更快,而不是別人認爲應該更快。 – 2012-07-28 17:19:43

+0

好點!作爲一名Java新手 - 目前沒有任何專門的java教科書 - 我意識到從壞習慣開始。雖然我相信在一天結束的時候我會有很多。 – 2012-07-28 17:32:41

回答

7

您最好只在最後創建並應用正則表達式替換一次。但是,你將獲得由

  • 初始化StringBuilder的一個合理的規模
  • 避免循環中的String創建多得多,並且讀人物直接追加到StringBuilder
  • 避免的實例化新的字符緩衝區,在任何時候,在每次迭代。

爲了避免不必要的長時間臨時字符串創建,您可以通過字符讀取char,並且只能將字符追加到StringBuilder,如果它是not a whitespace。最後,StringBuilder將只包含好字符,並且您不需要任何replaceAll()調用。

+0

謝謝!我現在要再看一遍。我已經爲stringbuilder的容量做了一個快速的Google,現在正在通過垃圾進行涉水。球公園,將幾千字節加載到緩衝區完全可以嗎? – 2012-07-28 17:43:29

+0

如果你的記憶允許,爲什麼不呢?一個StringBuilder只是一個字符數組的封裝。 – 2012-07-28 17:45:36

4

實際上有在這幾個代碼非常顯著效率低下,而且你不得不擔心你提出的相對不那麼重要的問題之前解決這些問題。

首先,不要在循環的每次迭代中創建新的buf對象 - 使用同一個對象!這樣做沒有問題 - 新數據會覆蓋舊的數據,並節省對象分配(這是您可以執行的更昂貴的操作之一)。

其次,同樣,請不要創建String請致電append() - 使用append的形式,該數組需要一個char數組和一個偏移量(在本例中爲0)和長度(在本例中爲numRead)。再次,每個循環迭代創建一個較少的對象。最後,要回答你實際問到的問題:在循環中這樣做會在每次迭代中創建一個String對象,但通過我們剛纔完成的調整,您將創建每個迭代的對象 - 所以在循環結束時刪除空白是明確的贏家!

+0

非常感謝.append()提示。只是習慣於用不同參數的方法覆蓋方法,這些方法對我來說都是陌生的。可以看到我還有很長的路要走。謝謝! – 2012-07-28 17:47:27

1

你要做解析一定程度上取決於,你可能會更好在單獨的步驟去除的空間可言,和分析過程中的不理會他們。

想要刪除所有空格也是相當罕見的。你確定你不想用單個空格替換多個空格嗎?

+0

是的,我認爲是。我要解析的文件基本上是一個多維數組,用括號和鍵值與等號分開。沒有字符串句子,只有名字和數字值。 – 2012-07-28 17:37:55