使用 Java 8 流在 LocalDate 属性 上的对象列表中查找最近日期

Find most recent date in a list of objects on LocalDate property using Java 8 stream

我有一个包含多个属性的对象列表,其中一个是 LocalDate。我想从此列表中找到日期最近的对象。

我对 Java 8 和使用流相当陌生。与大多数编程一样,似乎有不止一种方法可以给这只猫剥皮。这是我目前所拥有的。

list.stream().filter( object -> object.getId() == id
&& object.getCancelDate() == null 
&& object.getEarliestDate() != null)
.min( Comparator.comparing( LocalDate::toEpochDay )
.get();

这给了我 "Non-static method cannot be referenced from a static context" 的比较函数。

我也考虑过创建一个仅包含过滤后对象的日期的地图,到目前为止已经想出了类似的方法。

list.stream().filter( object -> object.getId() == id
&& object.getCancelDate() == null 
&& object.getEarliestDate() != null)
.map( data -> data.getEarliestDate() )
.collect( Collectors.toList() )

而且我不确定从那里去哪里,或者这是否有效。

我知道有一个简单的方法可以做到这一点,但我的大脑就是没有把这些点联系起来。

更新

感谢您的回复。我更新了我的代码 Optional<YourObject> recentObject = list.stream().filter(object -> object.getId() == id && object.getCancelDate() == null && object.getEarliestDate() != null) .max(Comparator.comparing(s -> s.getEarliestDate().toEpochDay()));

我现在遇到编译器错误 不兼容的类型。

Required:Optional<MyClass>
Found:Optional<capture<? extends MyClass>>

该方法确实扩展了MyClass,所以在Optional的类型声明中,我需要做类似MyClass.class的事情吗?

更新 2 感谢@Hogen 通过在末尾添加 .map() 来帮助修复编译器错误。这是更改后的样子。

Optional<MyClass> date = 
list.stream().filter(object -> object.getId() == id &&
object.getCancelDate() == null &&
object.getEarliestDate() != null)
.max(Comparator.comparing( s -> s.getEarliestDate()
.toEpochDay())).map(Function.identity());

但是,经过一些帮助,我能够想出一个解决方案,将地图移动到不同的位置,这样我就不会 运行 陷入使用扩展 class 的问题.

Optional<LocalDate> mostRecentDate = list.stream()
.filter(data -> data.getId() == id && data.getCancelDate() == null)
.map(MyObject::getEarliestDate)
.filter(Objects::nonNull)
.max(LocalDate::compareTo);

您主要关注的是:

Optional<YourObject> recentObject = list.stream()
        .filter(object -> object.getId() == id && object.getCancelDate() == null && object.getEarliestDate() != null)
        .max(Comparator.comparing(YourObject::getEarliestDate)); // max of the date for recency

来自LocalDate.compareTo

Compares this date to another date. The comparison is primarily based on the date, from earliest to latest. It is "consistent with equals", as defined by Comparable.

将其放入答案中以提高可见性。根据@nullpointer 的回答和@Holger 的建议,我得出了以下两个解决方案。

解决方案 1

Optional<MyClass> mostRecentDate = list.stream()
    .filter(myObject -> myObject.getId() == id &&
     myObject.getCancelDate() == null && myObject.getEarliestDate() != null)
    .max(Comparator.comparing( s -> s.getEarliestDate()
    .toEpochDay())).map(Function.identity());

解决方案 2

LocalDate mostRecentDate = list.stream()
    .filter(myObject -> myObject.getId() == id && myObject.getCancelDate() == null)
    .map(MyObject::getEarliestDate)
    .filter(Objects::nonNull)
    .max(LocalDate::compareTo)
    .orElse(null);

这两种解决方案都有效,但在我看来,第二种解决方案更清晰,也更明确。它删除了 .map(Function.identity()) 代码,正如@Holgen 在使用 Java 8 的新 Method Reference :: 时指出的那样,它实际上没有做任何事情。它还过滤对象列表并将日期映射到一个新列表,然后使用 .max() 和 compareTo() 方法而不是自定义函数。我认为自定义函数和无用的代码很混乱,对于任何阅读代码的人来说,可能会使它更难理解。

请注意,在第二个解决方案中,我还删除了可选 class。使用 .orElse() 满足返回实际 LocalDate class 而不是流中的选项。

感谢大家的帮助,希望这个回答对其他人有帮助。