Java Reference
In-Depth Information
* @return The featured books in this library mapped to their
* (possibly {@code null}) message; never {@code null}.
*/
public Map<Book, String> getFeaturedBooks() {
return this.featuredBooks;
}
}
Functional Iteration
One of the marks of pride in post-functional language communities is that nobody uses a for loop anymore.
The abandonment of the for keyword has become a minimally acceptable criteria for code, enforced
with righteous zeal. Instead, these languages provide an iterator method. Java 8 joins the ranks of these
post-functional languages with the forEach and forEachRemaining methods.
The Iterable interface now provides a forEach method. Some Java developers still don't know about
the Iterable interface, which was introduced in Java 5. It is the base class underlying all the Java SDK classes
that can provide an Iterator , and it is the class that enabled the enhanced for loop introduced in Java 5.
Since the new forEach method is on this widely implemented interface, all those implementing classes now
have a forEach method, as well.
Semantically, the forEach method is the same thing as a for loop: it takes a Consumer and executes it
for each element in the loop. Practically, however, it's an inside-out for loop. Instead of creating a structure
where you iterate over the collection and then execute a series of steps for each iteration, the forEach
method provides the series of steps to the collection, and the collection applies it to each element in order.
This allows the collection implementation to perform the iteration in the most efficient way possible. Even
better, the code is much more succinct and readable, as Listing 3-2 shows.
Listing 3-2. Printing out each of the topics using an enhanced for loop and forEach
for (Book book : library.getBooks()) {
System.out.println(book);
}
library.getBooks().forEach(System.out::println);
If you do have some legacy code where you are provided an Iterator , however, you can still use a
functional alternative to the loop. In this case, the method is forEachRemaining , which applies the lambda
to all the remaining elements of the iterator and exhausts it in the process.
The situation is slightly different for Map.forEach . Historically, Java has wanted you to think of a Map as
providing access to a Collection of Map.Entry objects. With Java 8 lambdas, they are breaking away from
that: the Map.forEach method does not take a Consumer of Map.Entry objects, but a rather BiConsumer of the
key and value pairs. On the one hand, this makes for reasonably nice-looking inline implementations, such
as in Listing 3-3: there is no more having to call entry.getKey() and entry.getValue() . On the other hand,
BiConsumer is an exotic functional type, and very few lambda manipulations or existing method definitions
play nicely with it.
Listing 3-3. Printing out each of the featured books using the Map version of forEach
library.getFeaturedBooks().forEach(
(book, msg) -> System.out.println(book + ": " + msg)
);
 
Search WWH ::




Custom Search