Java8如何用Stream与Lambda替换List对象null值替代for循环
报错原因
- 类型不匹配根源:
forEach方法入参要求是Consumer<T>函数式接口,该接口的核心方法accept返回值为void,仅支持执行无返回值的消费操作。你使用的三元运算符是有返回值的表达式:条件不满足的分支直接返回了Product类型的对象p,和方法要求的无返回值类型冲突,因此IDE抛出如下错误:
Required type:
void
Provided:
Product
- 逻辑隐藏bug:你写的
p.getIsBreakStock().equals(null)永远无法正确判断null值:如果isBreakStock字段本身为null,调用equals方法会直接抛出空指针异常;如果字段不为null,equals(null)永远返回false,完全达不到null判断的目的。判断null值应该使用== null或者JDK提供的java.util.Objects.isNull()方法。
正确实现方式
优先选择语义最清晰、和原逻辑一致的写法,直接遍历修改原集合元素即可,不需要强行转Stream:
import java.util.Objects; listProduct.forEach(p -> { // 正确判断null后赋值 if (Objects.isNull(p.getIsBreakStock())) { p.setIsBreakStock("NO"); } });
如果一定要显式使用Stream流,注意Stream是惰性求值,中间操作不会实际执行,必须搭配终端操作触发逻辑。注意peek仅推荐用于调试场景,业务修改优先用上面的forEach写法:
listProduct.stream() .peek(p -> { if (p.getIsBreakStock() == null) { p.setIsBreakStock("NO"); } }) // 任意终端操作都可以触发流执行,选无额外开销的即可 .forEachOrdered(p -> {});
如果你的业务场景不允许修改原集合元素,需要生成新的集合,可以用map映射生成新对象:
import java.util.stream.Collectors; List<Product> resultList = listProduct.stream() .map(p -> { // 此处根据实际情况做对象拷贝,避免修改原对象 Product product = new Product(p.getId(), p.getName() /* 按实际构造方法补全其他字段 */); if (Objects.isNull(product.getIsBreakStock())) { product.setIsBreakStock("NO"); } return product; }) .collect(Collectors.toList());
内容的提问来源于stack exchange,提问作者Luis Nox
相关产品推荐
相关产品推荐

