2011-11-10 18 views
1

幾乎每個我工作的項目都會有某種製表符分隔的文件,我需要讀入並返回查找Map它。我發現自己一遍又一遍地重寫相同的方法。我想創建更通用的東西,所以我不必一直複製和粘貼代碼。從下面的代碼,我只改變行9和16-19。所以我只改變了Map<key, value>,以及我想如何將數據輸入到Map中的實現。有沒有辦法從這個方法中創建一個通用的過程,所以每次我想調用這個方法時,我所需要的就是提供我如何將數據輸入到Map的實現,並以某種方式將Map更改爲更一般的類型,如好。如何創建讀取製表符分隔文件的通用過程,並從中返回通用映射

1. public Map<String, PackageLog> readAllLogsIntoMap(File file){ 
2.  if (!file.exists()) 
3.  { 
4.   return new HashMap <String, PackageLog>(); 
5.  } 
6.  BufferedReader reader = null; 
7.  FileReader fileReader = null; 
8.  String data = null; 
9.  Map <String, PackageLog> resultMap = new HashMap <String, PackageLog>(); 
10.  try 
11.  { 
12.   fileReader = new FileReader(file); 
13.   reader = new BufferedReader(fileReader); 
14.   while ((data = reader.readLine()) != null) 
15.   { 
16.    PackageLog pl = new PackageLog(data); 
17.    if(!pl.getPdfName().equals("")){ 
18.     resultMap.put(pl.getPdfName(), pl); 
19.    } 
20.   } 
21.  } catch(Exception e){ 
22.   
23.  } 
24.  finally 
25.  { 
26.   try{ 
27.    if (reader != null) reader.close(); 
28.    if (fileReader != null) fileReader.close(); 
29.   }catch(IOException ioe){ 
30.    
31.   } 
32.  } 
33.  return resultMap; 
34. } 

回答

3
  1. 將這個方法在一個抽象的Util類。使用泛型。
  2. 對抽象方法委託在第9和16-19行執行的邏輯。
  3. 定義在這個類

的使用這些抽象方法例如:

public abstract class ReaderUtil<K, V> { 

protected abstract Map<K, V> newMap(); 
protected abstract void doThings(String data, Map<K, V> resultMap); 

public Map<K, V> readAllLogsIntoMap(File file){ 
     if (!file.exists()){ 
      return newMap(); 
     } 
     BufferedReader reader = null; 
     FileReader fileReader = null; 
     String data = null; 
     Map <K, V> resultMap = newMap(); 
     try { 
     fileReader = new FileReader(file); 
     reader = new BufferedReader(fileReader); 
     while ((data = reader.readLine()) != null){ 
      doThings(data, resultMap); 
     } 
    } catch(Exception e){ 

    } 
    finally{ 
     try{ 
      if (reader != null) reader.close(); 
      if (fileReader != null) fileReader.close(); 
     } catch(IOException ioe){ 

     } 
    } 
    return resultMap; 
} 
} 

和可能的用途:

ReaderUtil<String, PackageLog> reader = new ReaderUtil<String, PackageLog>(){ 
    protected Map<String, PackageLog> newMap() { 
     return new HashMap<String, PackageLog>(); 
    } 
    protected void doThings(String data, Map<String, PackageLog> resultmap){ 
     PackageLog pl = new PackageLog(data); 
     if(!pl.getPdfName().equals("")){ 
      resultMap.put(pl.getPdfName(), pl); 
     } 
    } 
}; 
Map<String, PackageLog> myMap = reader.readAllLogsIntoMap(); 

考慮到你只需要newMap()方法如果你想提供不同的地圖實現。在聚合類中你可以做new HashMap<K, V>()

您可能還想定義用於處理異常的掛鉤方法(可重寫,可能爲空的方法)。

+0

這看起來很棒。我只有一個問題給你。我們真的需要'newMap()'方法嗎?所以當我們檢查'if(!file.exists())'時,我們可以只返回新的HashMap ();'?哈維有什麼問題嗎? –

+0

哦,我明白了,你確實回答了我的上述問題。但是,我不明白你的意思是什麼'考慮到你只需要newMap()方法,如果你想提供不同的地圖實現'。你能詳細說明嗎? –

+0

事實上,正如答案中所述,只有在實現可能需要提供'Map'('HashMap','TreeMap'等等)的不同實現時纔有必要。即使在這種情況下,它也可以簡化爲受保護的抽象類getMapClass(),甚至是泛型的,並通過反射來執行實例化。 –

1

Harry,考慮到Java對D類編程語言這樣的類型不太好的支持,你必須重構你的方法來得到像這樣的簽名:public Map<String, Object[]> csvToMap(File argFile, char argSeparator, Class[]) {}。然後,你會像這樣調用它:mymap = csvToMap("/tmp/some.log", ';', { Date.class, String.class, Double.class});。此調用可用於解析包含如下行的CSV文件:2011-11-23;Some Name;232.22

+0

其實,我會爲我自己的lib編寫這個函數。對於所有需要解析CSV文件並使用數據填充某個集合對象的情況,這對所有情況都很有用。 :) – DejanLekic

3

您可以執行以下操作。

public interface LookupKey<K, T> { 
    K keyFor(T t); 
} 

public <K, T> Map<K, T> readAllLogsIntoMap(File file, Class<T> tClass, LookupKey<K, T> lookupKey) { 
    BufferedReader reader = null; 
    Map<K, T> resultMap = new LinkedHashMap<K, T>(); 
    if (!file.exists()) 
     return resultMap; 
    try { 
     Constructor<T> tConstructor = tClass.getConstructor(String.class); 
     reader = new BufferedReader(new FileReader(file)); 
     String data; 
     while ((data = reader.readLine()) != null) { 
      T t = tConstructor.newInstance(data); 
      K key = lookupKey.keyFor(t); 
      if (key != null) 
       resultMap.put(key, t); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 

    } finally { 
     try { 
      if (reader != null) reader.close(); 
     } catch (IOException ignored) { 
     } 
    } 
    return resultMap; 
} 
+1

不錯的一個,彼得!:) – DejanLekic

+0

@Peter:是否有可能推廣到它可以返回一個List <>以及。現在它只返回地圖。如果你願意,我可以把它變成另一個問題 –

相關問題