Java Reference
In-Depth Information
builder . append ( "]" );
String result = builder . toString ();
Of course, this isn't particularly great code. It's pretty hard to see what it's doing without
walking through it step by step. With Java 8 we can write Example 5-12 , which makes our
intent much clearer using streams and collectors.
Example 5-12. Formatting artist names using streams and collectors
String result =
artists . stream ()
. map ( Artist: : getName )
. collect ( Collectors . joining ( ", " , "[" , "]" ));
Here, we use a map to extract the artists' names and then collect the Stream using Col-
lectors.joining . This method is a convenience for building up strings from streams. It lets
us provide a delimiter (which goes between elements), a prefix for our result, and a suffix for
the result.
Composing Collectors
Although the collectors we've seen so far are quite powerful, they become significantly more
so when composed with other collectors.
Previously we grouped albums by their main artist; now let's consider the problem of count-
ing the number of albums for each artist. A simple approach would be to apply the previous
grouping and then count the values. You can see how that works out in Example 5-13 .
Example 5-13. A naive approach to counting the number of albums for each artist
Map < Artist , List < Album >> albumsByArtist
= albums . collect ( groupingBy ( album -> album . getMainMusician ()));
Map < Artist , Integer > numberOfAlbums = new
new HashMap <>();
for ( Entry < Artist , List < Album >> entry : albumsByArtist . entrySet ()) {
numberOfAlbums . put ( entry . getKey (), entry . getValue (). size ());
Hmm, it might have sounded like a simple approach, but it got a bit messy. This code is also
imperative and doesn't automatically parallelize.
What we want here is actually another collector that tells groupingBy that instead of build-
ing up a List of albums for each artist, it should just count them. Conveniently, this is
Search WWH ::

Custom Search