请求将Java循环筛选Map列表逻辑转换为Streams实现
将循环逻辑转换为Java Streams实现
原循环实现代码(可正常运行):
List<Map<String, Object>> list1=new ArrayList<>(); List<Map<String, Object>> list2= new ArrayList<>(); for ( Map<String, Object> datElement: list()) { for (Entry<String, Object> val : datElement.entrySet()) { if (val.getKey().equalsIgnoreCase("rateID") ) { //int kel = (int) val.getValue(); if ( val.getValue().toString().equalsIgnoreCase("0")) { list1.add(datElement); } if (val.getValue().toString().equalsIgnoreCase("1")) { list2.add(datElement); } } } }
我尝试的Streams代码(存在问题):
List<Map<String, Object>> list1= list().stream() .map(l -> l.entrySet().stream() .filter( obj -> obj.getKey().equalsIgnoreCase("rateID")) .map( obj -> obj.getValue().toString().equalsIgnoreCase("0")) ).collect(Collectors.toList());
问题分析
你写的Streams代码错误在于:map操作会把每个Map转换成一个Stream<Boolean>,最终收集得到的是List<Stream<Boolean>>,完全不是目标类型List<Map<String,Object>>。我们需要先过滤出符合条件的Map,再进行分类收集。
方案1:分别收集list1和list2
这种方式和原逻辑对应,遍历两次源列表:
List<Map<String, Object>> list1 = list().stream() .filter(map -> map.entrySet().stream() .anyMatch(entry -> entry.getKey().equalsIgnoreCase("rateID") && entry.getValue().toString().equalsIgnoreCase("0"))) .collect(Collectors.toList()); List<Map<String, Object>> list2 = list().stream() .filter(map -> map.entrySet().stream() .anyMatch(entry -> entry.getKey().equalsIgnoreCase("rateID") && entry.getValue().toString().equalsIgnoreCase("1"))) .collect(Collectors.toList());
方案2:一次性分组(更高效)
使用Collectors.groupingBy可以只遍历一次源列表,同时完成分组,效率更高:
// 定义获取rateID值的逻辑(忽略大小写) Function<Map<String, Object>, String> rateIdClassifier = map -> map.entrySet().stream() .filter(entry -> entry.getKey().equalsIgnoreCase("rateID")) .map(entry -> entry.getValue().toString().toLowerCase()) .findFirst() .orElse(null); // 没有rateID的Map会被归类到null键下 Map<String, List<Map<String, Object>>> grouped = list().stream() .collect(Collectors.groupingBy(rateIdClassifier)); // 提取目标列表,没有匹配项时返回空列表 List<Map<String, Object>> list1 = grouped.getOrDefault("0", new ArrayList<>()); List<Map<String, Object>> list2 = grouped.getOrDefault("1", new ArrayList<>());
补充说明
- 方案1逻辑直观,和原循环一一对应,但需要遍历两次源列表;
- 方案2只遍历一次,更适合数据量较大的场景,同时还能处理不含
rateID的Map(可根据需求调整orElse的返回值); - 注意:原循环中如果一个Map存在多个匹配
rateID=0或rateID=1的条目,会被重复添加到对应列表中。而上述Streams方案只会添加一次该Map,若需要完全复刻原逻辑的重复添加行为,可改用flatMap展开所有匹配条目后收集,但通常场景下每个Map只会有一个rateID键,因此上述方案更合理。
内容的提问来源于stack exchange,提问作者naveen
相关产品推荐
相关产品推荐

