【发布时间】: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