16

I have an instance of OptionalLong. But one of my libraries requires an Optional<Long> as a parameter.

How can I convert my OptionalLong into an Optional<Long>?

I was dreaming about something like this:

OptionalLong secondScreenHeight = OptionalLong.of(32l); // or: OptionalLong.empty()
api.setHeight(secondScreenHeight.mapToRegularOptional()); // .mapToUsualOptional does not exist
slartidan
  • 18,794
  • 12
  • 78
  • 122
  • There are many variations, but most of them leverage `OptionalLong.isPresent()` to distinguish between the empty and non-empty cases. – John Bollinger Aug 13 '18 at 13:18
  • 5
    the question is why doesn't `OptionalLong` have no `map/filter` etc – Eugene Aug 13 '18 at 13:24
  • 6
    `api.setHeight(…)` should not expect an `Optional` as argument type. Then you will not have such problems. – Holger Aug 13 '18 at 13:39
  • @Holger In some cases it cannot easily be avoided (i.e. if `Long` is the value of a type argument of a generic method) – slartidan Aug 13 '18 at 13:42
  • 10
    Just don’t use `Optional` as parameter at all, whether generic or not. It's horrible to read. What does it mean to call `setHeight` with an empty optional argument? Do nothing? Then, don’t call it at all. `secondScreenHeight.ifPresent(api::setHeight)` makes much more sense. – Holger Aug 13 '18 at 13:49
  • 2
    To add to what Holger already pointed out, this is what IntelliJ would suggest you as well... *...Optional was designed to provide a limited mechanism for library method return types where there needed to be a clear way to represent "no result". Using a field with type java.util.Optional is also problematic if the class needs to be Serializable, [which java.util.Optional is not.](https://stackoverflow.com/questions/24547673/why-java-util-optional-is-not-serializable-how-to-serialize-the-object-with-suc)* – Naman Aug 13 '18 at 16:37
  • 6
    Why a bounty is opened here? The question received good answers – Mạnh Quyết Nguyễn Aug 19 '18 at 11:53

4 Answers4

13

You could do this:

final OptionalLong optionalLong = OptionalLong.of(5);

final Optional<Long> optional = Optional.of(optionalLong)
            .filter(OptionalLong::isPresent)
            .map(OptionalLong::getAsLong);
marstran
  • 22,917
  • 5
  • 54
  • 62
  • What I like about this solution is, that the initial variable is only used once. This makes it possible to create "long chains" in my code - I do not necessarily store the value in a variable. – slartidan Aug 13 '18 at 13:35
  • I like that it does not use old `if else` syntax, but only shiny new java-8 syntax! – slartidan Aug 13 '18 at 13:36
  • @slartidan well, still `if/else` inside filter and map though – Eugene Aug 13 '18 at 13:37
11

I don't know simpler solutions but this will do what you need.

OptionalLong secondScreenHeight = OptionalLong.of(32l);
Optional<Long> optional = secondScreenHeight.isPresent() 
    ? Optional.of(secondSceenHeight.getAsLong()) 
    : Optional.empty();
api.setHeight(optional);
Orest Savchak
  • 4,443
  • 1
  • 16
  • 26
  • I like about this solution, that it is readable and that the intent to remap the optional is clearly visible. – slartidan Aug 13 '18 at 14:17
6

One more possibility, though only from JDK 9 is via the new OptionalLong.stream() method, which returns a LongStream. This can then be boxed to a Stream<Long>:

OptionalLong optionalLong = OptionalLong.of(32);
Optional<Long> optional = optionalLong.stream().boxed().findFirst();

With JDK 8 something similar can be done, by stepping out to the Streams utility class in Guava:

Optional<Long> optional = Streams.stream(optionalLong).boxed().findFirst();
df778899
  • 10,365
  • 1
  • 22
  • 33
  • 5
    Also, `findAny` is 2 characters shorter. – Radiodef Aug 19 '18 at 22:36
  • I like about it, that it is short and does not rely on `isPresent`. However the intention is not as clearly visible as in some of the other answers. Thanks for sharing this solution! – slartidan Aug 20 '18 at 09:58
1

This should work.

Optional<Long> returnValue = Optional.empty();
if(secondScreenHeight.isPresent()) {
      returnValue = Optional.of(secondScreenHeight.getAsLong());
}
pvpkiran
  • 23,183
  • 6
  • 71
  • 112