19

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
  • 20,403
  • 15
  • 83
  • 131
  • 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
  • 6
    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
  • 11
    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

14

You could do this:

final OptionalLong optionalLong = OptionalLong.of(5);

final Optional<Long> optional = Optional.of(optionalLong)
            .filter(OptionalLong::isPresent)
            .map(OptionalLong::getAsLong);
marstran
  • 26,413
  • 5
  • 61
  • 67
  • 1
    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
  • 1
    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
10

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,529
  • 1
  • 18
  • 27
  • 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
5

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,703
  • 1
  • 24
  • 36
  • 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
  • 25,582
  • 8
  • 87
  • 134