Lars Hartviksen
Lars Hartviksen

Reputation: 1232

Is there a class like Optional but for non-optionals?

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

Answers (4)

Stephan Herrmann
Stephan Herrmann

Reputation: 8178

You seem to be looking for the type @NonNull Food.

Upvotes: 0

Anton Balaniuc
Anton Balaniuc

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

Holger
Holger

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

Grzegorz Piwowarek
Grzegorz Piwowarek

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

Related Questions