Skip to content
Peter Nerg edited this page Dec 8, 2017 · 18 revisions

Option

Represents optional values.
Instances of Option are either an instance of Some or None. Some holds a non-null value whilst None holds no value.

The purpose is of Option/Some/None pattern is to replace the ugly null checking that one is forced to in Java.

An example is the Map interface in Java. Performing a get(...) on the Map will yield either the value of the key or null in case no such key exists.

In Scala you'll get an Option which may contain a value (Some) or None in case there was no such key.

The examples provided on this Wiki are only a subset of the full functionality.
For a complete set of functionality and examples refer to the Java Doc

Some

Represents an Option holding a non-null value.
Null values are not allowed as they're by default a non-value and therefore are mapped to None.
Creating Options of type Some is straightforward.
Either use the implementation directly:

Option<String> option = new Some<>("Peter is Great!");

or use the factory/apply method from Option:

Option<String> option = Option.apply("Peter is Great!");

or one can add that Scala look-and-feel by importing helper methods from the companion class

import static javascalautils.OptionCompanion.Option;

Option<String> option = Option("Peter is Great!");
import static javascalautils.OptionCompanion.Some;

Option<String> option = Some("Peter is Great!");

None

Represents an empty Option.
Empty in the sense of not holding any value. In Java you would normally represent this by null.
But null is ugly and cannot be used in programming without constant null checking.
None allows for programmatic usage performing no actions. Creating Options of type None is straightforward.
Either use the implementation directly:

Option<String> option = new None<>();

or use the empty method from the Option:

Option<String> option = Option.empty();

or can use the apply method and supply null.

Option<String> option = Option.apply(null);

or one can add that Scala look-and-feel by importing helper methods from the companion class

import static javascalautils.OptionCompanion.None;

Option<String> option = None();

Note the null value provided to apply will yield an Option of type None.
Any of the factory methods (apply/empty) methods is preferred as it will return the singleton None since it anyways cannot represent a state, therefore reducing creation of unnecessary object instances.

Examples

The most obvious use case for Options are as return type from methods instead of possible null values.
E.g. the following operations returns a UserData object if a user with the provided name exists, None otherwise.

Option<UserData> getUser(String userName)

Option as Iterable

The Option interface extends Iterable thus it can be used in loops as any collection.
In practice this means that Some behaves as a collection with a single value and None is empty.

E.g. consider the Option

Option<String> option = ...;

Can be used in the imperative loop:

for(String s : option) 
  System.out.println(s);

But since it's an Iterable it can also use the more functional approach:

option.forEach(s->System.out.println(s));

Replacing ugly if-not-null checks

Consider the following code snippet. The Listener in this case is optional.
The classical way would have been to have code that did something like this

private final SomeListener listener;
public SomeClass(SomeListener listener) {
  this.listener = listener;
}

public void notifySomething(String message)  {
  if(listener != null) 
    listener.notify(message);
}

Now consider using Option that allows for neater programming constructs.

private final Option<SomeListener> listener;
public SomeClass(Option<SomeListener> listener) {
  this.listener = listener;
}

public void notifySomething(final String message)  {
  listener.forEach(l -> l.notify(message))
}

Replacing if-null-else statements

One can in a single statement replace the if-null-then-default code construct by getOrElse

Option<String> option = ...;   
String value = option.getOrElse(() -> "Some default value");

Mapping Options

Another example of using the Option is to translate it to something else, i.e. apply a mapping function.
In the code example below we apply a count of the string data thus rendering an Option of Integer type.
Now the result depends of course on the original option. If it was None then the result is of course None. In case of Some a new Some is rendered containing the result of the mapping function.

Option<String> option = ...;   
Option<Integer> o = option.map(s -> s.length());

Why not Optional

In Java8 Oracle has released their own version called Optional. So why not use it?
I personally don't like it. First off it's not an Iterable nor does it provide access to the Stream API.
This makes their Optional stand out in the way that the methods you can apply on it don't have a consistent look and feel compared to the ones you can perform on a collection. E.g.
The ifPresent method is equivalent to the forEach but has a strange name to it.
IfPresent sounds like it should return a boolean not have a side effect by taking a consumer

ifPresent(Consumer<? super T> consumer)

I pretty much see the Option as a single/empty sized collection and it should therefore behave as a collection.
Also the rather iffy way of constructing an Optional bugs me.

Optional.of(...)
//and 
Optional.ofNullable(...)

If you would supply a null value to the of method it would throw a NullPointerException.
This is just odd, why would you have an Optional that anyways only can be of type Some?
So you as programmer is forced to use the ofNullable method in case you want to avoid null checking your input.

Anyways these are some of the things that I don't like about the Optional implementation hence my own more Scala like Option is provided.