在 Optional<List<Entity>> 的情况下 orElseGet 如何工作

How does orElseGet work in case of an Optional<List<Entity>>

我有一个 class 的可选列表,即:Optional<List<MyEntity>> opListEntity

当 Optional 存在时,我需要将所有 MyEntity 映射到 MyEntityDto。如果 Optional 为空,我将 return 一个空的 ArrayList.


方法 1(非功能性):

注:myEntityMapper是映射器class的一个对象,它将MyEntity映射到MyEntityDto

List<MyEntityDto> res;
if (opListEntity.isPresent()) {
       res = opListEntity.get().stream()
            .map(myEntityMapper::entityToDto)
            .collect(Collectors.toList());
} else {
       res = new ArrayList<>();
}

这种方法很好,但 IntelliJ 建议将其转换为函数式表达式。我让 IntelliJ 进行转换,这就是我得到的:

方法二(函数表达式):

List<MyEntityDto> res = opListEntity.map(myEntities -> myEntities.stream()
            .map(myEntityMapper::entityToDto)
            .collect(Collectors.toList()))
     .orElseGet(ArrayList::new);

我不明白的是,在方法 2 @ line 1 中,为什么会有地图?

让我再解释一下。参见第三种方法:

方法三:

List<CustomerAddressEntity> myEntities = opListEntity
        .orElseGet(ArrayList::new);
List<MyEntityDto> res = myEntities.stream()
        .map(myEntityMapper::entityToDto)
        .collect(Collectors.toList());

方法 3 工作正常,但如果我尝试将方法 3 转换为方法 4,它不起作用。

方法四:

List<MyEntityDto> res = opListEntity.stream()
            .map(myEntityMapper::entityToDto)
            .collect(Collectors.toList()))
     .orElseGet(ArrayList::new);

为什么 方法 4 不起作用但 方法 2 有效?
mapapproach 2 @ line 1 中做什么?

我认为如果您将代码缩进一点以使其更容易发现,就会变得很明显:

List<MyEntityDto> res = opListEntity // Optional<List<MyEntity>>
    .map(
        myEntities -> myEntities.stream() // Stream<MyEntity>
            .map(myEntityMapper::entityToDto)  // Stream<MyEntityDto>
            .collect(Collectors.toList()) // List<MyEntityDto>
        )
    .orElseGet(ArrayList::new); // List<MyEntityDto>

Optional(如果存在)映射到将包含的列表转换为流、映射元素并构建集合的结果,或者(如果为空)映射到新的空列表。

在您的第 4 种方法中 opListEntity 是类型 Optional<List<MyEntity>>。现在它取决于您使用的 JDK 版本。在 JDK8 Optional 中没有 stream() 方法。

List<MyEntityDto> res = opListEntity.stream() // there is no such method in JDK8
    ...

自 JDK9 以来有一个 stream() 方法,但它当然会 return Stream<List<MyEntity>> 因为这是 Optional 的类型。但是要使映射正常工作,您需要 Stream<MyEntity>。为此,您可以使用 flatMap 方法映射 returned 流:

List<MyEntityDto> res = opListEntity.stream() // Stream<List<MyEntity>>
    .flatMap(List::stream) // Stream<MyEntity>
    .map(myEntityMapper::entityToDto)
...