Java Reference
In-Depth Information
iif
(
track
.
getLength
() >
60
) {
String name
=
track
.
getName
();
trackNames
.
add
(
name
);
}
});
});
return
return
trackNames
;
}
In step 1, we moved to using streams, but we didn't really get their full potential. In fact, if
anything the code is even less pretty than it was to begin with—d'oh! So, it's high time we
introduced a bit more stream style into our coding. The inner
forEach
call looks like a prime
target for refinement.
We're really doing three things here: finding only tracks over a minute in length, getting their
names, and adding their names into our name
Set
. That means we need to call three
Stream
operations in order to get the job done. Finding tracks that meet a criterion sounds like a job
for
filter
. Transforming tracks into their names is a good use of
map
. For the moment we're
still going to add the tracks to our
Set
, so our terminal operation will still be a
forEach
. If
Example 3-21. Refactor step 2: finding names of tracks over a minute in length
public
public
Set
<
String
>
findLongTracks
(
List
<
Album
>
albums
) {
Set
<
String
>
trackNames
=
new
new
HashSet
<>();
albums
.
stream
()
.
forEach
(
album
-> {
album
.
getTracks
()
.
filter
(
track
->
track
.
getLength
() >
60
)
.
map
(
track
->
track
.
getName
())
.
forEach
(
name
->
trackNames
.
add
(
name
));
});
return
return
trackNames
;
}
Now we've replaced our inner loop with something a bit more streamy, but we still have this
pyramid of doom in our code. We don't really want to have nested stream operations; we
want one simple and clean sequence of method calls.
What we really want to do is find a way of transforming our album into a stream of tracks.
We know that whenever we want to
transform
or
replace
code, the operation to use is
map
.
This is the more complex case of
map
,
flatMap
, for which the output value is also a
Stream