3

It seems for performance reasons OptionalDouble does not simply extend Optional<Double>? IMO, that's a perf concern that should not have leaked into SDK design but I digress.

As a library writer, which one should I expose to my users, Optional<T> or OptionalT? What factors would make me decide which one to use when?

EDIT: Based on the comments, elaborating my particular use case. I am writing a bridge to a Scala ML library so people can use it from Java 8+.

The boiled down Scala signature looks like this:

def flattenBy(f: Double => Option[Double]): List[Double]

For those not familiar with Scala, flattenBy is a function that takes in another function from Double to Option[Double] and returns a List of Doubles.

What is the closest signature this maps to in Java 8?

Community
  • 1
  • 1
pathikrit
  • 32,469
  • 37
  • 142
  • 221
  • 6
    Well `Optional` isn't an `Optional`, because the genuine primitive would be `double` - which isn't a valid type argument. – Jon Skeet Oct 20 '15 at 19:31
  • @JonSkeet: Sorry `Primitive` is a misnomer here (updated in edit) but the question still stands - which one is the preferred type to expose in APIs? – pathikrit Oct 20 '15 at 19:33
  • 2
    I think your question stems from a misunderstanding around the primitive wrapper classes (which isn't always helped by the JMV's "helpful" autoboxing). Primitives are just that - primitive. They're not instances of a class. They can be *boxed* to a corresponding class, but that does incur a performance hit, which is mentioned in your link. So to repeat what @JonSkeet said, `OptionalDouble` is not a subtype of `Optional`. – Thorn G Oct 20 '15 at 19:35
  • @TomG: I see. As a library writer, which one should I expose in my interface? If the answer is "it depends" - what does it depend on? When do I use one vs the other? – pathikrit Oct 20 '15 at 19:37
  • What is your use case? These classes are easy to misuse. – Paul Boddington Oct 20 '15 at 19:38
  • @PaulBoddington: I intentionally kept the question open-ended and not tied to a particular use case so readers can get general guidelines about what to apply where. I can elaborate on my particular use case if need be. – pathikrit Oct 20 '15 at 19:44
  • 1
    I doubt that there are noticeable performance differences. There is a semantic difference. An `Optional` doesn’t know whether it has to retain the object identity of the wrapped `Double` object (and will retain it), while for an `OptionalDouble`, it’s clear that the object identity is irrelevant (as there is none). – Holger Oct 20 '15 at 19:47
  • @Holger: Then I guess the question begs why didn't the Java library designers make `OptionalDouble` extend `Optional`? I got the performance as a reason from an accepted answer on SO that I linked in the OP: http://stackoverflow.com/questions/23323019/why-have-multiple-version-of-optional-in-java-8 – pathikrit Oct 20 '15 at 19:49
  • See the top answer here for general advice on when to use `Optional` and when not to use `Optional`: http://stackoverflow.com/questions/26327957/should-java-8-getters-return-optional-type. You should only return `Optional` if the identity is needed. In 99% of cases, you should use `OptionalDouble`. – Paul Boddington Oct 20 '15 at 20:00
  • 1
    There might be performance considerations—the same as for adding all the mirrored functional interfaces for `int`, `long` and `double`. But being based on performance considerations is not contradicting to *my* doubts about the practical consequences. And *you* might base your decision on either or both… – Holger Oct 20 '15 at 20:01
  • @PaulBoddington: My question is if I do decide to use Optionals, do I use `Optional` or `OptionalT`. Also, in this particular case, its not only something I am returning, its also an argument into an API I am exposing. I guess to further elaborate on my use case: I am providing a Java 8 bridge to my clients to a Scala ML library that uses `Option[X]` (in idiomatic Scala, `null`s are avoided and `Option[A]` is used instead). In my Java interface, which one do I expose? Also, I have complicated Scala signatures like `f: Double => Option[Double]`. What should that map to in JDK8+? – pathikrit Oct 20 '15 at 20:09
  • I don't know Scala at all I'm afraid. I don't really understand your question as there is no such thing as `OptionalT`. If your method is generic with type parameter `T`, your only choice is to return `Optional`. On the other hand if your method is not generic, then you should prefer `OptionalDouble` to `Optional`. You should not use an `Optional` as a method argument at all. As that link explains, they are only intended as return values. – Paul Boddington Oct 20 '15 at 20:14
  • @PaulBoddington: tl;dr: I have some function in Scala that accepts another function as an argument from `Double` to `Option[Double]`. In Scala, the signature for the latter function is `Double => Option[Double]`. What is the closest thing I should map to in Java 8? – pathikrit Oct 20 '15 at 20:17
  • You could pass a `DoubleFunction` – Paul Boddington Oct 20 '15 at 20:21
  • @PaulBoddington: I put my use case in the EDIT. And, yes, I could. But, what makes me decide `DoubleFunction` over `DoubleFunction>`? – pathikrit Oct 20 '15 at 20:22
  • You should only use an `Optional` if you actually need the the doubles to have an identity as well as a value (it sounds like you don't). It looks to me like it should be `List flattenBy(DoubleFunction f) {...}` – Paul Boddington Oct 20 '15 at 20:24
  • @PaulBoddington: Fair enough. Please put it as an answer so I can accept it. Alternatively, this question already has 4 close votes (not sure why?) so I guess its not appropriate for this site so feel free to close it too. – pathikrit Oct 20 '15 at 20:27
  • I have no idea why there are 4 close votes. It's not from me. I usually ask for clarification rather than vote to close. – Paul Boddington Oct 20 '15 at 20:31
  • 3
    Scala's `Optional` is not specialized, so it always contains an object value. So a direct mapping would be to a boxed `Double`. From a Java api design, if the signature is always a `Double` then prefer `OptionalDouble`. This will be more valuable when value types are supported. – Ben Manes Oct 20 '15 at 22:58

2 Answers2

4

It looks to me like the closest signature is:

List<Double> flattenBy(DoubleFunction<OptionalDouble> f)

You would only need to use Optional<Double> if it is necessary for the doubles to have an identity as well as a value (It sounds like you don't need this).

Paul Boddington
  • 37,127
  • 10
  • 65
  • 116
1

It seems for performance reasons OptionalDouble does not simply extend Optional? IMO, that's a perf concern that should not have leaked into SDK design but I digress.

That's not quite what the linked answer says. It explains that OptionalDouble exists at all because of the performance concern. But given that it does it can't extend Optional<Double> because the signatures are incompatible: its get returns double, Optional<Double>'s one returns Double.

If you don't care about types other than double, sure, use OptionalDouble; but consider that List<Double> has a much worse overhead (3 times the memory use of double[] in this example)! There are many libraries providing real primitive collections for Java: e.g. HPPC, Trove, fastutil, Koloboke.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487