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

How to apply a condition only if an optional is present?

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

Stream<LocalDate> dates = ...;   
Optional<LocalDate> dateOptional = ...;

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

我是这样写Predicate的:

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

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

重点是 Predicate<T> 必须 return 一个始终导致 boolean 的表达式。

因为 Localdate::isAfter returns boolean 你可以使用 Predicate<LocalDate> 里面的 Optional 的优势,结果是 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);

别忘了,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>

我发现对于这样的问题,使用 LocalDate.MIN 几乎总是可以接受的,因为它会产生最简单、最易读的代码。

LocalDate date = getOptionalDate().orElse(LocalDate.MIN);
dateStream.filter(d -> !d.isAfter(date));

有一个轻微的边缘情况,如果您的流包含等于 LocalDate.MIN 的值,那么它会在不应该包含的时候被包含。鉴于 LocalDate.MIN 代表公元前约 1000 亿年,这种边缘情况对于所有意图和目的而言与大多数应用程序无关