如何将 Optional<T> 转换为 Stream<T>?

77

我想在一个流前面添加一个Optional。由于Stream.concat只能连接流,所以我有一个问题:

如何将Optional<T>转换为Stream<T>?

示例:

Optional<String> optional = Optional.of("Hello");
Stream<String> texts = optional.stream(); // not working

1
请参见以下链接:https://dev59.com/t2Eh5IYBdhLWcg3wKgug - Alexis C.
那个问题确实回答了这个问题,但它提供了一个更复杂的例子。我认为这个简单情况值得保留。 - Didier L
7个回答

150
如果受限于Java-8,您可以这样做:

Stream<String> texts = optional.map(Stream::of).orElseGet(Stream::empty);

5
我给这个点赞是因为Java 9对一些当前状态下的项目有一些不兼容的变化。一些项目,比如lombok,是核心企业工件的一部分,更改较慢。 - Niko
如果你的可选项恰好包含一个 List<String> 而不是单个的 String 对象,那么你只需要将 Stream::of 替换为 List::stream。对于任何其他类型的集合也适用。你也可以使用 Collection::stream。否则你会得到一个 Stream<List<String>>,这可能 不是 你想要的。 - walen
@walen 这个问题是将 Optional<T> 转换为 Stream<T>,如果 T 是 List<String>,那就是它。答案仍然正确。你可能正在寻找的是展平集合。此外,如果你最终使用了 Optional<Collection<T>>,那么你已经走错了路。 - Naman
@Naman 不需要为答案辩解 - 我并没有说它不正确。我只是给了一个提示,关于如何将这个解决方案应用到包含List的Optional中,这是一些人可能会遇到的情况。 - walen

83

在Java 9中,新增了缺失的stream()方法,因此该代码可以工作:

在Java 9中新增了stream()方法,因此此代码可正常运行:

Stream<String> texts = optional.stream();

请查看JDK-8050820。在此处下载Java-9


8

如果你没有使用Java 9,我可以推荐使用GuavaStreams.stream(optional)方法。这是一个简单的例子:

Streams.stream(Optional.of("Hello"))

也可以使用静态导入Streams.stream,这样你只需写
stream(Optional.of("Hello"))

8

您可以做以下操作:

Stream<String> texts = optional.isPresent() ? Stream.of(optional.get()) : Stream.empty();

14
我不是“isPresent”的铁粉,它给我一种遗留代码的感觉,让我想起Java8之前的时代。但感谢您提供了另一种解决方案。 - slartidan
map().orElseGet() 方法不太流畅,但可能稍微更有效率。 - augurar

1

这取决于您希望如何将空可选项转换为流元素。如果您想将其解释为“无内容”(或“无元素”):

Stream<String> texts = optional.stream(); // since JDK 9
Stream<String> texts = optional.map(Stream::of).orElseGet(Stream::empty); // JDK 8

但如果您想将其解释为空值:
Stream<String> texts = Stream.of(optional.oreElse(null));

1
如果你使用的是旧版本Java(比如安卓系统),并且正在使用aNNiMON轻量级流API,那么你可以按照以下方式进行操作:
    final List<String> flintstones = new ArrayList<String>(){{
        add("Fred");
        add("Wilma");
        add("Pebbles");
    }};

    final List<String> another = Optional.ofNullable(flintstones)
            .map(Stream::of)
            .orElseGet(Stream::empty)
            .toList();

这个例子只是复制了列表。

0
我以前的同事开发了一个很好的库叫做Streamify,它可以从几乎任何东西中创建流。

https://github.com/sourcy/streamify

从可选项创建流到streamify中的表单:
Streamify.stream(optional)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接