仅当存在可选项时如何应用条件?

Joo*_*ila 1 java predicate optional java-8 java-stream

我有一个Optional<LocalDate>对象和一个Stream其他日期。

Stream<LocalDate> dates = ...;   
Optional<LocalDate> dateOptional = ...;
Run Code Online (Sandbox Code Playgroud)

我想过滤掉可选的所有日期。如果可选项不存在,过滤器不应该做任何事情。

我写过Predicate这样的:

Predicate<LocalDate> predicate = date -> !dateOptional.isPresent() || !date.isAfter(dateOptional.get());  
Stream<LocalDate> filteredStream = dates.filter(predicate);
Run Code Online (Sandbox Code Playgroud)

我想避免使用isPresent()get()。是否有更实用的方式来编写相同的逻辑?我正在使用 Java 8。

Nik*_*las 7

关键是Predicate<T>必须返回一个始终产生 a 的表达式boolean

由于您可以使用的Localdate::isAfter回报boolean具有Optional内部Predicate<LocalDate>和结果的优势boolean

Optional<LocalDate> dateOptional = ...;
                                                        // Together Predicate<LocalDate>
Predicate<LocalDate> predicate = date -> dateOptional   // .. Optional<LocalDate>
     .map(d -> !date.isAfter(d))                        // .. Optional<Boolean>
     .orElse(true);                                     // .. Boolean


Stream<LocalDate> filteredStream = dates.filter(predicate);
Run Code Online (Sandbox Code Playgroud)

不要忘记,Stream<LocalDate>在终端操作之前保持打开状态。


编辑:感谢@Holger:整个过程predicate可能会被优化以避免重复和不必要的调用:

Predicate<LocalDate> predicate = dateOptional                 // Optional<LocalDate>
    .<Predicate<LocalDate>>map(d -> date -> !date.isAfter(d)) // Optional<Predicate<LocalDate>>
    .orElse(date -> true);                                    // Predicate<LocalDate>
Run Code Online (Sandbox Code Playgroud)

  • 这是执行不必要的操作。由于“Optional”在流操作期间不会更改(甚至不允许更改),因此您无需重复测试每个流元素的可选值是否存在。相反,使用 `Predicate&lt;LocalDate&gt; predicate = dateOptional.&lt;Predicate&lt;LocalDate&gt;&gt;map(d -&gt; date -&gt; !date.isAfter(d)).orElse(date -&gt; true);` 你甚至可以走一步进一步,当可选值为空时,不将 `filter` 操作链接到流: `Stream&lt;LocalDate&gt; FilteredStream = dateOptional .map(d -&gt; rates.filter(date -&gt; !date.isAfter(d))) .orElse (日期);` (3认同)