java lambda中的嵌套List Hashmap处理

时间:2016-04-25 13:41:22

标签: java java-8

我有一些情况,我有包含地图名称页面集合的页面列表,在页面地图中我有另一个列表调用组,如下所示:

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()));

但是无法过滤掉页面意味着如果页面不包含任何组,那么我需要删除该页面用户单个语句lambda,我可以使用传统的Java迭代过程来完成它,它看起来像:

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();
            }
        }
    }
}

但我需要lambda解决方案。

1 个答案:

答案 0 :(得分:3)

首先,当你想要修改集合时,Streams不是正确的工具,但请注意集合本身有几个有用的方法。

如果您想获得最大化lambda使用率的奖品,您可以使用:

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,它仍然可以工作,并不比基于lambda的用法复杂:

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的类型,代码更简单,需要一个未经检查的类型转换......