Java Reference
In-Depth Information
There are a few key things to notice in Listing 3-4. Note that using the functional interfaces allows us
to ensure we are using the same code for both the topics list and the featured books set: any change to the
predicate would be reliably applied in both cases. Also notice that the removeIf call entirely removes the
iteration code in both places, leaving us with much cleaner and descriptive code. Since the featured books
set is a strict subset of the topics list, we can use the return value of the first call as an optimization to
short-circuit our removal: if we found no books matching the genre, then there is no reason to check the
featured books list. The use of functional code here saves us a lot of boilerplate and noise, and the variable
names become labels describing what the function does. When you have behavior as variables, it is a lot
easier to produce self-documenting code.
Listing 3-4. A Library instance method to remove genres using removeIf
/**
* Maps an element to a value and then tests that mapped value.
*
* @param map The function that defines the map; never {@code null}
* @param test The function that defines the test; never {@code null}
* @return A predicate that tests the result of the mapping of its argument.
*/
private static <T,U> Predicate<T> mapThenTest(
Function<T,U> map, Predicate<U> test
) {
Objects.requireNonNull(map, "the map implementation");
Objects.requireNonNull(test, "the test implementation");
return t -> test.test(map.apply(t));
}
/**
* Removes all books of the given genre from both the library collection
* and the featured collection.
*
* @param genre The genre to compare against; never {@code null}.
*/
public void removeGenre(Book.Genre genre) {
Objects.requireNonNull(genre, "the genre to compare against");
Predicate<Book> hasGenre = mapThenTest(Book::getGenre, genre::equals);
if (this.getBooks().removeIf(hasGenre)) {
this.getFeaturedBooks().keySet().removeIf(hasGenre);
}
}
Mapping Collections and Maps
If you have embraced a more functional style of development, you are probably using a lot of immutable
objects. In this chapter, we are taking that approach with our Book class. However, this leads to a problem
when we want to manipulate the objects: for instance, say that we want to add a star after the title if it is
featured. Since the Book instances are immutable, we will need to replace the old instances with our new
instances. To do this, we can use the List.replaceAll method. The method is attached to List and not to
Collection because replacing elements in some kinds of collections raises awkward situations for their API,
such as in the case of SortedSet . (If you transform the sorted elements of a SortedSet, what sorting do you
apply to the result?)
 
Search WWH ::




Custom Search