将 Java 8 的 Optional 与 Stream::flatMap 一起使用

发布于 2022-05-26 23:11:12

新的 Java 8 流框架和朋友们编写了一些非常简洁的 java 代码,但我遇到了一个看似简单但很难做到简洁的情况。

考虑一个List<Thing> thingsand 方法Optional<Other> resolve(Thing thing)。我想将 s
映射ThingOptional<Other>s 并获得第一个Other.
显而易见的解决方案是使用things.stream().flatMap(this::resolve).findFirst(),但flatMap要求您返回一个流,并且Optional没有stream()方法(或者它是
aCollection还是提供将其转换为或查看为 a 的方法Collection)。

我能想到的最好的是:

things.stream()
    .map(this::resolve)
    .filter(Optional::isPresent)
    .map(Optional::get)
    .findFirst();

但对于一个非常常见的情况来说,这似乎是非常冗长的。有人有更好的主意吗?

关注者
0
被浏览
10
1 个回答
  • 面试哥
    面试哥 2022-05-26
    为面试而生,有面试问题,就找面试哥。

    爪哇 9

    Optional.stream已添加到
    JDK 9。这使您能够执行以下操作,而无需任何辅助方法:

    Optional<Other> result =
        things.stream()
              .map(this::resolve)
              .flatMap(Optional::stream)
              .findFirst();
    

    爪哇 8

    是的,这是 API 中的一个小漏洞,因为将 aOptional<T>转换为 0 或 1 的长度有点不方便Stream<T>。你可以这样做:

    Optional<Other> result =
        things.stream()
              .map(this::resolve)
              .flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
              .findFirst();
    

    但是,在内部使用三元运算符flatMap有点麻烦,因此最好编写一个小辅助函数来执行此操作:

    /**
     * Turns an Optional<T> into a Stream<T> of length zero or one depending upon
     * whether a value is present.
     */
    static <T> Stream<T> streamopt(Optional<T> opt) {
        if (opt.isPresent())
            return Stream.of(opt.get());
        else
            return Stream.empty();
    }
    
    Optional<Other> result =
        things.stream()
              .flatMap(t -> streamopt(resolve(t)))
              .findFirst();
    

    在这里,我将调用内联resolve()而不是进行单独的map()操作,但这是个人喜好问题。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看