I have two Optional
strings, name1
and name2
. I want to join the two such that the result is also an Optional with:
AND
.Optional
My attempt at this:
StringBuilder sb = new StringBuilder();
name1.ifPresent(sb::append);
name2.ifPresent(s -> {
if (sb.length() > 0) {
sb.append(" AND ");
}
sb.append(s);
}
Optional<String> joinedOpt = Optional.ofNullable(Strings.emptyToNull(sb.toString()));
This works, but seems ugly and not very functional.
PS: There is a similar question but the accepted answer is wrong. Specifically, if name1
is empty and name2
is not, it returns an empty optional.
One solution is to stream and reduce()
:
Optional<String> joinedOpt = Stream.of(name1, name2)
.filter(Optional::isPresent)
.map(Optional::get)
.reduce((a, b) -> a + " AND " + b);
Feel free to replace the filter/map combo with Java 9 or Guava as others have suggested.
Possible solution in Java 1.9 would be
Optional<String> name1 = Optional.of("x");
Optional<String> name2 = Optional.of("y");
String s = Stream.concat(name1.stream(), name2.stream()).collect(Collectors.joining(" AND "));
System.out.println(s);
With Java 1.8 there is no way that you can go from an Optional to a Stream. However, you can add such a conversion quite easily to Java 1.8.
static <T> Stream<T> of(Optional<T> option) {
return option.map(Stream::of).orElseGet(Stream::empty);
}
And now you can use the of
method to concatenate both streams.
Now, to get an empty Optional
if there is no result, you can wrap the result into an Optional and do a simple filter.
Optional<String> result = Optional.of(collect).filter(Optional::isPresent);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With