Reputation: 1232
It is handy to declare Functions to map values and consume them if they are present.
In the situation that you have several mandatory objects, and several Optionals, I find myself wrapping the others in Optional.of(mandatoryObject) as well so I can use the same expressions on them without writing it all backwards.
Food vegetables = Food.someVegetables();
Optional<Food> condiment = Food.someCondiment();
Optional<Food> spices = Food.someSpices();
condiment.map(prepare).ifPresent(putOnPlate);
spices.map(prepare).ifPresent(putOnPlate);
But then I don't like this code:
putOnPlate.accept(prepare.apply(vegetables));
so I wrap it:
Optional.of(vegetables).map(prepare).ifPresent(putOnPlate);
But that is just wrong, because the vegetables (in this example) are not in fact optional. They are very important and I just gave everyone the impression that they are optional.
So my question is : Is there some class in java like java.util.Mandatory so I can write:
Mandatory.of(vegetables).map(prepare).definitelyPresentSo(putOnPlate);
Upvotes: 44
Views: 2334
Reputation: 11739
I might be wrong, but if you don't like to use Optional
you can just use a Stream
of just one object. So instead of
Optional.of(vegetables).map(prepare).ifPresent(putOnPlate);
you can just use:
Stream.of(vegetables).map(prepare).forEach(putOnPlate);
The result is going to be identical. Both methods will throw NPE
if vegetables are null.
Arrays.asList(10, null).forEach(value -> {
Optional.of(value).map(x -> x.toString()).ifPresent(System.out::println);
Stream.of(value).map(x -> x.toString()).forEach(System.out::println);
});
NPE safe version is going to be
Optional.ofNullable(value).map(x -> x.toString()).ifPresent(System.out::println);
Stream.of(value).filter(Objects::nonNull).map(x -> x.toString()).forEach(System.out::println);
Optional
is just a container for an object which may or may not contain a non-null value.
Upvotes: 4
Reputation: 298379
Yes, there is such an API. You may replace
Optional.of(vegetables).map(prepare).ifPresent(putOnPlate);
with
Stream.of(vegetables).map(prepare).forEach(putOnPlate);
now having to live with the fact that the single-element Stream
is a special case of the stream of arbitrary elements (including the possible empty stream).
But you can handle all mandatory elements at once
Stream.of(mandatory1, mandatory2, mandatory3 /* etc */).map(prepare).forEach(putOnPlate);
It would be even possible to incorporate the optional elements, but it will not be as convenient as it should be, as Optional.stream()
will be introduced not until Java 9.
Upvotes: 27
Reputation: 13803
The main idea behind Optional
is abstracting nullability(getting rid of null checks) and providing a fluent API for working with optional values.
In the case of a value that is always present, there is nothing to abstract(at least nothing with a practical value) so no such tools exist in the pure Java.
In other functional languages, you have multiple 'monadic' tools like Optional
available for different use-cases. If you want to bring them to Java, Javaslang is probably the best place to look at. You can find there tools like Option
, Try
, Lazy
, Validation
, Either
, Future
, Tuple
and the whole Collections API
that allows coding in a similar fashion you described.
Upvotes: 10