【问题标题】:How to Filter a map of map based on another map using Lamda expressions如何使用 Lambda 表达式根据另一个地图过滤地图地图
【发布时间】:2019-08-11 18:09:48
【问题描述】:

我有一个 Map 需要使用 lambda 表达式基于另一个 Map 进行过滤

我尝试在地图上进行过滤并根据另一张地图查找所有匹配项,但它似乎不起作用。似乎没有正确过滤这些值。 有没有办法可以进行流和映射并将过滤逻辑放在那里? 有人可以帮忙吗

 public static void main(String []args){
    System.out.println("Hello World");
    Map<String,List<String>> items = new HashMap<>();
    List<String> ut1=new ArrayList<>();
    ut1.add("S");
    ut1.add("C");
    List<String> ut2=new ArrayList<>();
    ut2.add("M");
    List<String> ut3=new ArrayList<>();
    ut3.add("M");
    ut3.add("C");
    items .put("1010016",ut1);
    items .put("1010019",ut2);
    items .put("1010012",ut3);
    System.out.println("Map"+items);

    Map<String,Map<String,String>> sKey = new HashMap<>();
    Map<String,String> utKey1 = new HashMap<>();
    utKey1.put("S","1001");
    utKey1.put("M","1002");
    utKey1.put("C","1003");

    Map<String,String> utKey2 = new HashMap<>();
    utKey2.put("S","1004");

    Map<String,String> utKey3 = new HashMap<>();
    utKey3.put("S","1005");
    utKey3.put("M","1006");

    Map<String,String> utKey4 = new HashMap<>();
    utKey4.put("S","1007");
    utKey4.put("M","1008");
    utKey4.put("C","1009");

    sKey.put("1010016",utKey1);
    sKey.put("1010019",utKey2);
    sKey.put("1010012",utKey3);
    sKey.put("1010011",utKey4);

    System.out.println("Map2"+sKey);

    Map<String,Map<String,String>> map3 =
        sKey.entrySet().stream()
            .filter(x -> 
                items.containsKey(x.getKey())
                && x.getValue().entrySet().stream().allMatch(y -> 
                    items.entrySet().stream().anyMatch(list ->
                        list.getValue().contains(y.getKey()))))
            .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
    System.out.println("Map3"+map3);
 }

过滤后的地图返回:

地图3{1010012={S=1005, M=1006}, 1010016={S=1001, C=1003, M=1002}, 1010019={S=1004}}

但实际结果应该是:

地图3{1010012={M=1006}, 1010016={S=1001, C=1003}}

【问题讨论】:

  • 乍一看,我看不出您是如何达到预期结果的。我正在重新格式化代码,以便我现在可以阅读它
  • 您的 Stream 管道采用输入映射,过滤掉其中的一些条目,并构建所有未过滤掉的条目的映射。因此,您不能期望新映射中的键与输入映射中的相同键具有不同的值。
  • 有更好的方法吗?而不是使用 allMatch 和 anyMatch?
  • 尝试重新阅读重新格式化的代码,我认为它更清楚地显示了问题。您将需要新的列表,我会在您的收集器中这样做。使用 Map#keySet 和 Set#retainAll 将大大缩短这段代码
  • 有没有办法可以进行流和映射并在那里编写所有过滤逻辑?我试过这样做,但没有成功。

标签: java filter java-stream


【解决方案1】:

我宁愿说这是一种使用流实现预期输出的解决方法。

Map<String, Map<String, String>> result = 
    sKey.entrySet().stream()
    .filter(detail -> items.keySet().contains(detail.getKey()) && 
            !Collections.disjoint(detail.getValue().keySet(), items.get(detail.getKey())))
    .collect(HashMap::new, 
            (m,v) -> m.put(v.getKey(), v.getValue().entrySet().stream()
                .filter(detail -> items.get(v.getKey()).contains(detail.getKey()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))), 
            HashMap::putAll);

输出

{1010012={M=1006}, 1010016={S=1001, C=1003}}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多