我正在将一些代码移动到java8,尝试(有时强迫自己)使用stream和lambdas,我对它们感到不舒服。
我在类中有一些验证业务对象的方法。每个方法都是
Optional<Fail> validate1(BusinessObject bo)
其中Fail是以某种方式描述错误的枚举,如果没有错误,则该方法返回Optional.empty()。我不需要收集所有错误,但返回第一个错误,而不执行以下验证。
我正在做的是
//first convert methods to suppliers
Supplier<Optional<Fail>> validate1= () -> validate1(bo);
Supplier<Optional<Fail>> validate2= () -> validate2(bo);
Supplier<Optional<Fail>> validate3= () -> validate3(bo);
//then some stream magic
return Stream.of(validate1, validate2, validate3)
.map(Supplier::get)
.filter(f -> f.isPresent())
.findFirst()
.orElse(Optional.empty()); //without the orElse, no error would return
// Optional(Optional.empty())
// instead of Optional.empty()
它有效,它完成工作,它不执行不必要的方法,它是清晰的(如果Optional.orElse被命名为getOrElse,它会更清晰,但这是我无法实现的)。我想要找出的是,如果这是一个合理的方式来做我想要的,如果这个代码被认为是'好风格'或'惯用java8',或者我误用Stream或Optional,或者遗漏了一些明显的东西。
返回第一个非空的可选或者一个空的可选,如果它们都是空的,看起来很通常认为有一个正式的方法可以做到这一点,我脑子里的东西是大喊“Monads!”,但是我对Haskell的无知几乎是完美的,所以我不知道。
答案 0 :(得分:2)
Optional
很像Stream
,其中包含0或1个元素。但它没有实现Stream
,也没有stream()
方法(就像集合一样)。
但是,将Optional<T>
转换为Stream<T>
并不困难,此功能可以实现:
public static <T> Function<Optional<? extends T>, Stream<T>> asStream() {
return op -> op.map(Stream::of).orElseGet(Stream::empty);
}
使用该方法,您只需使用flatMap:
Stream.of(validate1, validate2, validate3)
.map(Supplier::get)
.flatMap(asStream())
.findFirst();