2016-04-25 56 views
2

我有一些情況下,我有一個包含地圖名稱頁,並在頁面的地圖我還有一個列表呼叫組,這是看起來像集合頁面列表:嵌套列表的Hashmap處理Java中的λ

List<Map<String,Object>> group = new ArrayList<>(); 
Map<String,Object> groupMap = new HashMap<>(); 
groupMap.put("G1F1", null); //<-- null value need to remove from groupMap 
groupMap.put("G1F2", "F2value"); 
groupMap.put("G1F3", "F3value"); 
groupMap.put("G1F4", null);//<-- null value need to remove from groupMap 
group.add(groupMap); 

Map<String,Object> groupMap2 = new HashMap<>(); 
groupMap2.put("G2F1", null);//<-- null value need to remove from groupMap2 
groupMap2.put("G2F2", "F2value"); 
groupMap2.put("G2F3", "F3value"); 
groupMap2.put("G2F4", null);//<-- null value need to remove from groupMap2 
group.add(groupMap2); 

Map<String,Object> page1 = new HashMap<>(); 
page1.put("PageID", "PID1001"); 
page1.put("Groups", group); 

Map<String,Object> page2 = new HashMap<>();//<-- page2 do not have Groups need to remove from pages 
page2.put("PageID", "PID1208"); 
Map<String,Object> page3 = new HashMap<>();//<-- page3 do not have Groups need to remove from pages 
page3.put("PageID", "PID1212"); 
Map<String,Object> page4 = new HashMap<>();//<-- page4 do not have Groups need to remove from pages 
page4.put("PageID", "PID1214"); 
Map<String,Object> page5 = new HashMap<>(); 
page5.put("PageID", "PID15555"); 
page5.put("Groups", group); 

pages.add(page1); 
pages.add(page2); 
pages.add(page3); 
pages.add(page4); 
pages.add(page5); 

在上面的頁面對象我需要刪除那些沒有任何組的頁面,並且在組中我需要刪除那些具有空值的項目。

我試着用下面的代碼使用java8 lamda,但輸出是意想不到的,就像[true, true, false, false]

Object object = pages.stream().filter(page -> page.containsKey("Groups")) 
    .map(page -> (List) page.get("Groups")) 
      .flatMap(x -> x.stream()).map(group -> ((Map<String,Object>)group).entrySet().removeIf(g -> g.getValue() == null)).collect(Collectors.toList()); 

我能夠去除其中由下面的代碼包含空值的組中的所有項目:

pages.stream().filter(page -> page.containsKey("Groups")) 
    .map(page -> (List) page.get("Groups")).flatMap(x -> x.stream()).forEach(group -> ((Map<String,Object>)group).entrySet().removeIf(entry -> null == entry.getValue())); 

但不能濾除頁面意味着如果頁面DONOT包含任何

private static void sanitizePages() { 
    Iterator<Map<String,Object>> listIt = pages.iterator(); 
    while(listIt.hasNext()) { 
     Map<String,Object> item = listIt.next(); 

     if(!item.containsKey(("Groups"))){ 
      listIt.remove(); 
      continue; 
     } 
     List<Map<String,Object>> groups = (List<Map<String,Object>>)item.get("Groups"); 
     Iterator<Map<String,Object>> groupsIt = groups.iterator(); 

     while(groupsIt.hasNext()) { 
      Map<String,Object> map = groupsIt.next(); 
      Iterator<Entry<String, Object>> groupIt = map.entrySet().iterator(); 
      while(groupIt.hasNext()) { 
       Entry<String,Object> group = groupIt.next(); 
       if(null == group.getValue()) groupIt.remove(); 
      } 
     } 
    } 
} 

但我需要拉姆達的解決方案:組,那麼我需要刪除該網頁的用戶單個語句拉姆達,我可以使用傳統的Java迭代過程,這是看起來像做。

回答

3

首先,當您想要修改集合時,流並不是正確的工具,但請注意,集合本身有幾個有用的方法。

如果你想贏得最大化的λ使用獎品,你可以使用:

pages.removeIf(item -> { 
    List<Map<String,Object>> groups = (List<Map<String,Object>>)item.get("Groups"); 
    if(groups==null) return true; 
    groups.forEach(map -> map.values().removeIf(Objects::isNull)); 
    return false; 
}); 

但要注意,有良好的老方法,如removeAll仍然工作,並且並不比拉姆達更復雜基於使用:

Set<Object> nulls=Collections.singleton(null); 
pages.removeIf(item -> { 
    List<Map<String,Object>> groups = (List<Map<String,Object>>)item.get("Groups"); 
    if(groups==null) return true; 
    groups.forEach(map -> map.values().removeAll(nulls)); 
    return false; 
}); 

當然,代碼是簡單的,如果集合沒有用Object類型,需要一個未經檢查的類型轉換...

+0

ACTUA lly我開始研究lamda,它看起來比傳統的編程風格更加緊湊,請問我能解釋爲什麼stream不是正確的修改集合的工具,是性能問題還是最好不要使用流進行收集修改 – Assad

+0

這不是他們的預期用途。一般來說,不鼓勵在傳遞給Stream操作的函數中產生副作用。如果副作用違反了[不干擾](https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#NonInterference)約束,則代碼必須是被認爲是中斷的(並且可能導致異常,或者甚至更糟糕的是,在運行時無聲的數據損壞;根據情況,它有時甚至可能看起來有效)。流可以處理集合中的元素,您可以將結果收集到新的集合中,但不能修改它們。 – Holger

+0

這並不意味着您無法使用lambda表達式簡化集合操作。您可以使用Collection API提供的新方法,如我的答案中所示。這些不會與Stream API混淆。請參閱'Iterable.forEach'和'Collection.removeIf'(在我的回答中都使用)或'List.replaceAll','Map.forEach','Map.merge'等。 – Holger