使用Java Streams遍历JsonNode元素抛出NoSuchElementException如何处理
问题根本诱因
你猜测的switch分支return引发异常是错误的,实际诱因如下:
Stream.generate()生成的是无界流,默认会持续生成元素直到触发终端操作的终止逻辑,本身不会感知迭代器的元素边界jsonNode.fields()返回的是Iterator<Map.Entry<String, JsonNode>>类型的迭代器,迭代器的next()方法在没有剩余元素时,会直接抛出java.util.NoSuchElementException,而你的代码完全没有做hasNext()边界判断。
举个实际场景示例:如果你的JsonNode里只有a、b两个合法字段,且两个字段的校验都返回true,此时allMatch()还会继续向流索要下一个元素,触发迭代器的next()调用,而迭代器已经没有剩余元素,就会抛出异常。
正确实现方案
最兼容Java 8+、也最稳妥的方案是用StreamSupport将迭代器转换为有界流,它会自动关联迭代器的hasNext()判断,不会越界调用next():
return StreamSupport.stream( Spliterators.spliteratorUnknownSize(jsonNode.fields(), Spliterator.ORDERED), false ) .allMatch(entry -> { switch (entry.getKey()) { case "a": return evaluateA(entry.getValue()); case "b": return evaluateB(entry.getValue()); default: return false; } });
如果你使用Java 9及以上版本,也可以用takeWhile()做边界截断,但要注意该方案执行顺序是先生成元素再做边界判断,最后一个元素会被过滤,仅适合特殊场景使用:
Iterator<Map.Entry<String, JsonNode>> fieldIter = jsonNode.fields(); return Stream.generate(fieldIter::next) .takeWhile(ignore -> fieldIter.hasNext()) .allMatch(entry -> { switch (entry.getKey()) { case "a": return evaluateA(entry.getValue()); case "b": return evaluateB(entry.getValue()); default: return false; } });
内容的提问来源于stack exchange,提问作者drunkenfist
相关产品推荐
相关产品推荐

