2017-01-06 207 views
1

我有一個ResultSet包含300K記錄,我正在做以下操作來迭代它(以及其他操作一旦收集)。此過程需要大約2分鐘才能完成。有什麼辦法可以優化它嗎?迭代優化HashMap

Map<String,Map<String,String>> internalMap = new HashMap<String,Map<String,String>>(); 

while (resultSet.next()) { 
    final Integer val1 = resultSet.getInt("val1"); 
    final String val2 = resultSet.getString("val2"); 
    final String val3 = resultSet.getString("val3"); 
    final String val4 = resultSet.getString("val4"); 
    final String type = resultSet.getString("type"); 
    final String id = resultSet.getString("id"); 

    addIntern(internalMap,val2,val1,val3,val4,type,id); 
} 

而且addIntern上述方法

private static void addIntern(Map<String,Map<String,String>> internalMap, String val2, Integer val1, 
    String val3,String val4,String type,String id) { 
    String key = id+"##"+val4; 
    if (internalMap.get(key) == null) { 
     internalMap.put(key, new HashMap<String,String>()); 
    } 
    internalMap.get(key).put("val3", val3); 
    internalMap.get(key).put("val2", val2); 


    if("create".equals(type)){ 
     internalMap.get(key).put("create", val1.toString()); 
    } 
    if("update".equals(type)){ 
     internalMap.get(key).put("update", val1.toString()); 
    } 
    if("delete".equals(type)){ 
     internalMap.get(key).put("delete", val1.toString()); 
    } 
} 
+3

它看起來像你需要一個'Map '而不是'Map >' – 4castle

+0

@ 4castle但是我們只是把值。因此,將它用作對象或地圖,兩者都會產生相同的效果。對? – NaaN

+1

使用'Map '將會使用更多的內存,並且對於您可以存儲的值的類型來說,靈活性會更低。例如,您已經不得不將'val1'轉換爲'String'。 – 4castle

回答

5

調整你的resultSet;

resultSet.setFetchSize(100); 

而且你當然可以簡化你的add方法(分別獲得是O(1)電話,但他們加起來),像

private static void addIntern(Map<String, Map<String, String>> internalMap, String val2, Integer val1, String val3, 
     String val4, String type, String id) { 
    String key = id + "##" + val4; 
    Map<String, String> kMap; 
    if (internalMap.containsKey(key)) { 
     kMap = internalMap.get(key); 
    } else { 
     kMap = new HashMap<>(); 
     internalMap.put(key, kMap); 
    } 
    kMap.put("val3", val3); 
    kMap.put("val2", val2); 
    if ("create".equals(type) || "update".equals(type) || "delete".equals(type)) { 
     kMap.put(type, val1.toString()); 
    } 
} 
1

引用您將無法優化很多,因爲你不能減少迭代次數。

但是一個變化,我可以看到這是可以做到

if("create".equals(type)){ 
    internalMap.get(key).put("create", val1.toString()); 
} 
if("update".equals(type)){ 
    internalMap.get(key).put("update", val1.toString()); 
} 
if("delete".equals(type)){ 
    internalMap.get(key).put("delete", val1.toString()); 
} 

上面可以寫爲下面還

internalMap.get(key).put(type, val1.toString()); 

這將消除30萬次以上,如果檢查。

這將適用於您的type只能包含create/update/delete值的情況。如果它有更多,你可以把一個if來檢查它是否等於任何一個3.

0

試試這個。 (Java 8)

private static void addIntern(Map<String,Map<String,String>> internalMap, 
    String val2, Integer val1, 
    String val3,String val4,String type,String id) { 
    String key = id+"##"+val4; 
    Map<String, String> valueMap = internalMap.computeIfAbsent(key, k -> new HashMap<>()); 
    valueMap.put("val3", val3); 
    valueMap.put("val2", val2); 
    if("create".equals(type) || "update".equals(type) || "delete".equals(type)) 
     valueMap.put(type, val1.toString()); 
} 
0

設置地圖的初始容量可能會幫助,如果你有足夠的可用堆空間:

Map<String,Map<String,String>> internalMap = new HashMap<String,Map<String,String>>(300000*2); 

通過使用默認的初始容量,internalMap必須因爲你添加被重新散列多次300000項。