连接Java 8中的两个或多个可选字符串

ric*_*din 5 string concatenation optional java-8

对你们来说,我有一个很简单的问题。在Java 8中引入了Optional类型。我有两个类型的对象,Optional<String>我想知道哪种是更优雅的连接它们的方法。

Optional<String> first = Optional.ofNullable(/* Some string */);
Optional<String> second = Optional.ofNullable(/* Some other string */);
Optional<String> result = /* Some fancy function that concats first and second */;
Run Code Online (Sandbox Code Playgroud)

详细地说,如果两个原始Optional<String>对象之一等于Optional.empty(),我也希望整个串联也为空。

请注意,我不是在问如何Optional在Java中连接两个Strings的求值,而是要在一个内部连接两个s Optional

提前致谢。

ric*_*din 5

我找到的解决方案如下:

first.flatMap(s -> second.map(s1 -> s + s1));
Run Code Online (Sandbox Code Playgroud)

可以使用专用方法清洁,例如:

first.flatMap(this::concat);
Optional<String> concat(String s) {
    second.map(s1 -> s + s1);
}
Run Code Online (Sandbox Code Playgroud)

但是,我认为可以找到更好的方法。

如果要泛化为的列表或数组Optional<String>,则可以使用类似于以下内容的内容。

Optional<String> result =
    Stream.of(Optional.of("value1"), Optional.<String>empty())
          .reduce(Optional.of(""), this::concat);

// Where the following method id used
Optional<String> concat(Optional<String> first, Optional<String> second) {
    return first.flatMap(s -> second.map(s1 -> s + s1));
}
Run Code Online (Sandbox Code Playgroud)

请注意,为了编译以上代码,我们必须手动将类型变量绑定Optional.empty()String

  • 如果“first”为空而“second”不为空,则first.flatMap(s -&gt; secondary.map(s1 -&gt; s + s1)) 将返回空,这是不正确的。也就是说:`Optional.empty().flatMap(s -&gt;Optional.of("second").map(s1 -&gt; s + s1))`将返回empty(),而不是`"second"` 。 (2认同)

lma*_*arx 5

您可以流式传输Optionals 并使用 减少它们concat

Optional<String> first = Optional.of("foo");
Optional<String> second = Optional.of("bar");
Optional<String> result = Stream.of(first, second).flatMap(Optional::stream).reduce(String::concat);
Run Code Online (Sandbox Code Playgroud)

如果您使用的是 Java 8,请将flatMap运算符替换为filter(Optional::isPresent).map(Optional::get)

还可以考虑使用joining收集器:这将返回String,而不是Optional<String>