245. Transforming values via Map() and flatMap()

The Optional.map() and flatMap() methods are convenient for transforming an Optional value.

The map() method applies the function argument to the value, then returns the result wrapped in an Optional object. The flatMap() method applies the function argument to the value and then returns the result directly.

Let's assume that we have Optional<String>, and we want to transform this String from lowercase into uppercase. An uninspired solution can be written as follows:

Optional<String> lowername = ...; // may be empty as well

// Avoid
Optional<String> uppername;

if (lowername.isPresent()) {
uppername = Optional.of(lowername.get().toUpperCase());
} else {
uppername = Optional.empty();
}

A more inspired solution (in a single line of code) will rely on Optional.map(), as follows:

// Prefer
Optional<String> uppername = lowername.map(String::toUpperCase);

The map() method can be useful to avoid breaking a chain of lambdas as well. Let's consider List<Book>, and we want to find the first book that's $50 cheaper and, if such a book exists, change its title to uppercase. Again, an uninspired solution will be as follows:

private static final String NOT_FOUND = "NOT FOUND";
List<Book> books = Arrays.asList();
...
// Avoid
Optional<Book> book = books.stream()
.filter(b -> b.getPrice()<50)
.findFirst();

String title;
if (book.isPresent()) {
title = book.get().getTitle().toUpperCase();
} else {
title = NOT_FOUND;
}

Relying on map(), we can do it via the following chain of lambdas:

// Prefer
String title = books.stream()
.filter(b -> b.getPrice()<50)
.findFirst()
.map(Book::getTitle)
.map(String::toUpperCase)
.orElse(NOT_FOUND);

In the preceding example, the getTitle() method is a classical getter that returns the title of the book as String. But let's modify this getter to return Optional:

public Optional<String> getTitle() {
return ...;
}

This time, we cannot use map() because map(Book::getTitle) will return  Optional<Optional<String>> instead of Optional<String>. But if we rely on flatMap(), then the return of it will not be wrapped in an additional Optional object:

// Prefer
String title = books.stream()
.filter(b -> b.getPrice()<50)
.findFirst()
.flatMap(Book::getTitle)
.map(String::toUpperCase)
.orElse(NOT_FOUND);

So, Optional.map() wraps the result of transformation in an Optional object. If this result is Optional itself, then we obtain Optional<Optional<...>>. On the other hand, flatMap() does not wrap the result within an additional Optional object.

 

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.26.22