2012-04-19 105 views
2

我有一個用Java編寫的程序,它只讀取一個文件,該文件只是一個字符串列表到一個LinkedHashMap中。然後它需要第二個文件,它由兩列組成,每行查看右邊的術語是否與HashMap中的某個術語匹配。問題是它運行速度很慢。Java - 比較列表

這裏的代碼片段,這是它比較第二檔到HashMap中的術語:

String output = ""; 

infile = new File("2columns.txt"); 
     try { 
      in = new BufferedReader(new FileReader(infile)); 
     } catch (FileNotFoundException e2) { 
      System.out.println("2columns.txt" + " not found"); 
     } 

     try { 
      fw = new FileWriter("newfile.txt"); 

      out = new PrintWriter(fw); 

      try { 
       String str = in.readLine(); 

       while (str != null) { 
        StringTokenizer strtok = new StringTokenizer(str); 

        strtok.nextToken(); 
        String strDest = strtok.nextToken(); 

        System.out.println("Term = " + strDest); 

        //if (uniqList.contains(strDest)) { 
        if (uniqMap.get(strDest) != null) { 
         output += str + "\r\n"; 
         System.out.println("Matched! Added: " + str); 
        } 

        str = in.readLine(); 
       } 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

      out.print(output); 

我從一個ArrayList最初轉換到LinkedHashMap的得到了性能提升,但它仍然需要很長時間。我能做些什麼來加快速度?

+4

剖析你的代碼並找出瓶頸。優化最大的一個。沖洗並重復。 – 2012-04-19 03:44:54

+2

僅供參考,我只會使用HashMap而不是LinkedHashMap,因爲LinkedHashMap不僅維護'map',而且還維護所有值的'鏈接列表',以在迭代元素時保持插入順序。除非你需要這個特定的好處,否則我會改成HashMap。 – 2012-04-19 03:47:59

+2

我同意@MДΓΓБДLL,你的問題缺乏關於你的應用程序發生緩慢的足夠信息。文件是否如此龐大以至於您的應用程序正在將內存交換到磁盤?磁盤IO能夠很慢嗎?現在的程序現在運行多長時間?你需要多快才能運行?在你的WHILE循環中你實例化一個新的StringTokenizer;循環內的對象實例化代價很高。如果文件足夠大,打印可能會導致緩慢,您也可以在循環中使用System.out.println。確定緩慢來自何處。 – 2012-04-19 03:53:17

回答

4

您的主要瓶頸可能是您正在爲while循環的每次迭代重新創建一個StringTokenizer。將此移到循環外可能會有相當大的幫助。通過在while循環外部移動字符串定義可以獲得較小的速度提升。

最大的加速可能來自使用StreamTokenizer。見下面的例子。

哦,使用HashMap,而不是作爲LinkedHashMap的艾爾斯@Doug說,在上述評論:)

而@剖析你的代碼MДΓΓБДLL的建議是喋喋不休。結帳這個Eclipse Profiling Example

Reader r = new BufferedReader(new FileReader(infile)); 
StreamTokenizer strtok = new StreamTokenizer(r); 
String strDest =""; 
while (strtok.nextToken() != StreamTokenizer.TT_EOF) { 
    strDest=strtok.sval; //strtok.toString() might be safer, but slower 
    strtok.nextToken(); 

    System.out.println("Term = " + strtok.sval); 

    //if (uniqList.contains(strDest)) { 
    if (uniqMap.get(strtok.sval) != null) { 
     output += str + "\r\n"; 
     System.out.println("Matched! Added: " + strDest +" "+ strtok.sval); 
    } 

    str = in.readLine(); 
} 

最終的一個想法是(我不相信在這一個)寫入文件也可能更快,如果你在年底一氣呵成做到這一點。即將所有的比賽存儲在某種緩衝區中,並在一次打擊中進行書寫。

2

StringTokenizer是一個遺留類。建議的替換是字符串「拆分」方法。

某些trys可能會合並。一次嘗試可以有多個捕獲。

建議使用HashMap而不是LinkedHashMap,這是一個很好的建議。由於不需要維護列表結構,因此可以更快速地獲取和放入smidgeon。

「輸出」字符串應該是一個StringBuilder而不是一個字符串。這可以幫助很多。