Java 映射筛选器列表会导致额外的空项
我有一个简单的类,如下所示:Java 映射筛选器列表会导致额外的空项,java,dictionary,java-stream,Java,Dictionary,Java Stream,我有一个简单的类,如下所示: public class ListOfMapsExample { public static void main(String[] args) { Map<String, String> map1 = Map.of("aa1k", "aa1v", "aa2k", "aa2v", "aa3k", "aa3v");
public class ListOfMapsExample {
public static void main(String[] args) {
Map<String, String> map1 = Map.of("aa1k", "aa1v", "aa2k", "aa2v", "aa3k", "aa3v");
Map<String, String> map2 = Map.of("bb1k", "bb1v", "bb2k", "bb2v", "bb3k", "bb3v");
Map<String, String> map3 = Map.of("cc1k", "cc1v", "cc2k", "cc2v", "cc3k", "cc3v");
List<Map<String, String>> maps = Arrays.asList(map1, map2, map3);
List<Map<String, String>> listOfMaps1 = maps.stream()
.map(m -> m.entrySet().stream()
.filter(map -> map.getKey().equals("aa1k") || map.getKey().equals("bb2k"))
.collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue())))
.collect(Collectors.toList());
System.out.println("listOfMaps1 :: " + listOfMaps1);
}
}
公共类列表示例{
公共静态void main(字符串[]args){
Map map1=地图的地图(“aa1k”、“aa1v”、“aa2k”、“aa2v”、“aa3k”、“aa3v”);
Map map2=地图的位置(“bb1k”、“bb1v”、“bb2k”、“bb2v”、“bb3k”、“bb3v”);
Map map3=地图的地图(“cc1k”、“cc1v”、“cc2k”、“cc2v”、“cc3k”、“cc3v”);
listmaps=Arrays.asList(map1、map2、map3);
List listOfMaps1=maps.stream()
.map(m->m.entrySet().stream())
.filter(map->map.getKey().equals(“aa1k”)| | map.getKey().equals(“bb2k”))
.collect(Collectors.toMap(p->p.getKey(),p->p.getValue()))
.collect(Collectors.toList());
System.out.println(“listOfMaps1::”+listOfMaps1);
}
}
预期产出:
listOfMaps1::[{aa1k=aa1v},{bb2k=bb2v}]
实际产量:
listOfMaps1::[{aa1k=aa1v},{bb2k=bb2v},{}]
问题:
即使第三个映射没有通过筛选条件,为什么它在结果中显示为空?我怎么能省略它呢?您正在通过过滤每个内容来构建地图。其中一个将为空,因为没有传递任何值(但您仍然创建了它)。因此,在将空映射添加到列表之前,需要对其进行筛选
List<Map<String, String>> listOfMaps1 = maps.stream()
.map(m -> m.entrySet().stream()
.filter(map -> map.getKey().equals("aa1k")
|| map.getKey().equals("bb2k"))
.collect(Collectors.toMap(p -> p.getKey(),
p -> p.getValue()))).filter(map->!map.isEmpty())
.collect(Collectors.toList());
System.out.println("listOfMaps1 :: " + listOfMaps1);
List listOfMaps1=maps.stream()
.map(m->m.entrySet().stream())
.filter(map->map.getKey().equals(“aa1k”)
||map.getKey().equals(“bb2k”))
.collect(Collectors.toMap(p->p.getKey()),
p->p.getValue()).filter(map->!map.isEmpty())
.collect(Collectors.toList());
System.out.println(“listOfMaps1::”+listOfMaps1);
问题已经在WJS的答案中解释过了,但根据您的示例,您可能可以使用替代(而且我的可读性稍高)解决方案:
- 展平流以迭代所有贴图中的条目
- 从我们感兴趣的流中筛选条目
- 将筛选条目中的数据重新包装到映射中
- 在列表中收集所有此类地图
列表
List listOfMaps1=maps.stream()
.flatMap(m->m.entrySet().stream())//创建所有条目的单个流
.filter(entry->entry.getKey().equals(“aa1k”)| | entry.getKey().equals(“bb2k”))
.map(entry->map.of(entry.getKey(),entry.getValue())
.collect(Collectors.toList());
输出:
listOfMaps1::[{aa1k=aa1v},{bb2k=bb2v}]
通过检查条目是否为空,为列表中的MAPS1
添加另一个过滤器。也许更好的代码格式可以改进您的问题。在映射
列表中的每个映射只保留键为“aa1k”
或“bb2k”
的键值对后,将转换为另一个映射。由于只有前两个映射包含带有这些键的kvp,因此输出的第三个映射将为空。旁白:您可能需要重新考虑是否确实要收集到列表
,或者仅仅是映射
或列表
。是否有一种方法可以按键对列表进行排序?有一个微妙之处。这些地图正在相互独立地进行处理。因此,在地图上复制关键点不是问题。但在您的情况下,如果其中一个贴图确实有重复的关键点,则将创建第三个贴图来处理它。当然,没有人知道数据的约束或性质,也没有人知道是否存在重复项。@AjayKumar是的。在将条目包装到Map之前,只需添加.sorted(Comparator.comparing(Map.Entry::getKey))
,所以可能在.filter(…)
@WJS之后,我想我明白你的意思了。我的印象是,每个生成的映射应该始终包含单个键值对,但操作代码取决于输入和过滤(比如,如果他正在搜索a
b
和c
),也可能得到类似[{a-a1,b-b1},{c-c1}]
,而我的代码将生成[{a-a1},{b-b1},{c-c1}]
@Pshemo是的。这是我测试它时得到的。但是你的答案会更清晰。我想只有OP才能根据他们对数据的熟悉程度做出决定。Offtopic:“aa1k”.equals(map.getKey())会比map.getKey().equals(“aa1k”)更好
List
List<Map<String, String>> listOfMaps1 = maps.stream()
.flatMap(m -> m.entrySet().stream()) //to create single stream of all entries
.filter(entry -> entry.getKey().equals("aa1k") || entry.getKey().equals("bb2k"))
.map(entry -> Map.of(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());