将Java传统循环代码转换为Stream流时遇空指针问题求助
问题:Stream实现移除孤立节点时抛出空指针异常
需求:移除输入Map<String, List<Element>>(键为rootId,值为包含根节点、普通节点、叶子节点的列表)中无对应根节点的节点与叶子节点。已有可正常运行的传统循环实现,但转成Stream流实现时,getCurrentOperations()方法抛出空指针异常。
原有工作代码
@NotNull private static Map<String, List<Element>> removeOrphanNodes(Map<String, List<Element>> mapOfAllProcesses) { Map<String,List<Element>> refinedRootMap= new HashMap<>(); for(Map.Entry<String,List<Element>>entrySet: mapOfAllProcesses.entrySet()) { if(entrySet.getValue().size()>1) refinedRootMap.put(entrySet.getKey(),entrySet.getValue()); else { Element loneElement = entrySet.getValue().get(0); if (entrySet.getKey().equals(loneElement.getIdAsString())) refinedRootMap.put(entrySet.getKey(),entrySet.getValue()); else if(loneElement.getCurrentOperations()!=null && loneElement.getCurrentOperations().iterator().next().getId().toHexString().equals(entrySet.getKey())) refinedRootMap.put(entrySet.getKey(),entrySet.getValue()); } } return refinedRootMap; }
尝试的Stream代码
return mapOfAllProcesses.entrySet().stream().filter(entry -> entry.getValue().size()>1 || entry.getValue().stream() .anyMatch( element-> element.getIdAsString().equals(entry.getKey())||element.getCurrentOperations().stream().findFirst().get().getId().toHexString().equals(entry.getKey()) )).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
问题原因分析
原有循环代码中,对loneElement.getCurrentOperations()做了非空判断,同时通过iterator().next()隐含了对集合非空的检查;但Stream版本中直接调用element.getCurrentOperations().stream(),如果getCurrentOperations()返回null就会触发空指针。另外,findFirst().get()会在currentOperations为空时抛出NoSuchElementException,也是潜在风险。
修复后的Stream实现
return mapOfAllProcesses.entrySet().stream() .filter(entry -> { List<Element> elements = entry.getValue(); // 列表元素数量大于1,直接保留 if (elements.size() > 1) { return true; } // 处理单个元素的情况 Element loneElement = elements.get(0); String rootId = entry.getKey(); // 元素自身是根节点 boolean isSelfRoot = rootId.equals(loneElement.getIdAsString()); // 检查currentOperations是否存在匹配的根节点 boolean hasMatchingOperation = Optional.ofNullable(loneElement.getCurrentOperations()) .stream() .flatMap(Collection::stream) .findFirst() .map(op -> op.getId().toHexString().equals(rootId)) .orElse(false); return isSelfRoot || hasMatchingOperation; }) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
修复点说明
- 用
Optional.ofNullable()包裹getCurrentOperations(),避免空指针 - 用
flatMap将集合转为流,替代直接调用stream() - 用
map()+orElse(false)安全处理findFirst()的结果,避免NoSuchElementException - 逻辑和原有循环完全对齐,保证一致性
内容的提问来源于stack exchange,提问作者Varun Yadav
相关产品推荐
相关产品推荐

