This course will be retired on July 14, 2025.
Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Well done!
You have completed Introduction to Functional Programming!
Preview
Video Player
00:00
00:00
00:00
- 2x 2x
- 1.75x 1.75x
- 1.5x 1.5x
- 1.25x 1.25x
- 1.1x 1.1x
- 1x 1x
- 0.75x 0.75x
- 0.5x 0.5x
Sometimes you only want to keep certain elements from your stream, filtering helps do just that.
Learn more
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
All right,
we now have a list of Java jobs.
0:00
I'd like to figure out which of those
jobs are here in Portland where I live.
0:03
I'm sure every single one of those
jobs aren't here in town, so
0:07
I'll need to filter out
the ones in Portland Oregon.
0:11
So let's take a quick second and
solve the problem imperatively first, and
0:14
then we'll get declarative.
0:18
So this is a pretty common ceremony
that we need to do, right.
0:20
So I'm gonna get rid of this line here.
0:23
So what we need to do is loop
through these jobs, right.
0:26
So we say for (Job job : jobs),
right, this jobs that was passed in.
0:30
And let's see, if the job, so
0:35
there is a thing here called getState()
and I need to see Oregon, and
0:39
Oregon is OR not to be confused with or.
0:43
We wanna look at everything
words in Portland, so
0:48
we wanna get where the job
state is Oregon and the city
0:52
equals("Portland"), okay.
0:58
So, we're gonna open that if block and
close that and
1:04
then we wanna print that out, right.
1:07
So, that's gonna print all of the jobs
that are in Portland, Oregon.
1:11
Let's run that.
1:13
Okay, so we've got like, five jobs
that were posted here in the last day.
1:15
Now, note,
1:19
this is the results of the toString
method that's in the job class here.
1:20
If we go take a look at Job,
there's a toString method here.
1:24
So that's what's going on.
1:28
That's what this mess here is.
1:29
So now, let's refactor this
into a method of itself.
1:33
So we can keep it around for
reference, so I'm gonna come up and
1:37
choose Refactor this and
I am going to choose Method.
1:40
And we will make this a private method,
and
1:46
we're gonna name it printPortlandJobs.
1:51
Imperatively, I'm gonna say, okay.
1:56
And it'll take a list of jobs.
1:59
So now, we can come back and
take a look at what we had before.
2:02
So, now,
let's do this declaratively, right?
2:04
So there's several ways to
create streams from our data but
2:09
most collections offer
a new stream method.
2:12
Let's call it.
2:15
So we have jobs, right?
2:15
So jobs is a collection, it's a list.
2:16
We're gonna say stream.
2:18
Okay so what did we want to do?
2:21
Yeah, we want to filter the jobs
that are in Portland, Oregon.
2:23
So now, quite intuitively we just say
that we want to filter the stream.
2:27
So we say .filter.
2:31
As you can see, it takes a predicate,
which was the function shape that we saw
2:34
that takes an item, and
then returns a boolean a true or false.
2:38
So the way that the filter method works
is if the predicate returns true,
2:43
it will keep the item.
2:47
So the item in this case
is going to be a job.
2:49
So why don't we name our parameter job?
2:53
And remember,
it's gonna figure out the type, right?
2:57
It's gonna know that it is of type job,
just by the way it's working.
3:00
Pretty cool, right?
3:03
Because it's only one parameter, I don't
need the parenthesis In the body of
3:04
the lambda will be to get the state and
see if it equals Oregon, right.
3:09
So we're gonna say
job.getState().equals("OR").
3:14
Now, remember this equals
method returns a true or
3:20
false and automatically
the return statement is assumed.
3:23
So it's gonna return true or false.
3:28
It's gonna return whatever this is.
3:30
So let's introduce some manners early,
here on.
3:32
Now, filter is an intermediate method.
3:35
Now, remember that each call
to these intermediate methods
3:38
is going to return a stream, so
that you can chain them together.
3:41
And these get pretty long pretty quick.
3:44
So typically, each of these
are written on a line all their own.
3:47
Now, it's a little strange
looking at first but
3:52
I promise you, if you see them written all
out in one line you will go "rude".
3:54
And fix it, just like this.
4:00
They pile up pretty quick.
4:03
Now, speaking of which,
let's add another filter here.
4:05
So we need to get the city, right?
4:12
So we'll do job, we're
gonna do job.getCity,
4:13
we'll say equals Portland.
4:18
So, now we have two
intermediate operations,
4:23
now we need to add a terminal operation.
4:27
So, very similar to how iterables
provide a forEach method, so
4:30
does the stream interface.
4:34
So let's do that, forEach, and
4:35
then we're gonna use our method
reference to print line on System.out.
4:40
So System.out and
we'll just get to print line here so
4:47
we'll print each one of those
through in I need a semicolon.
4:52
Okay, so we are gonna run this code,
let's take a look.
4:55
And, boom, it works, same five jobs.
5:02
Now, did anything in that feel weird?
5:05
Were you wondering why we made two
5:08
filter statements instead of one
expression like we did here?
5:10
Does writing two methods here feel like
we are doing extra unnecessary work?
5:14
Now, it does seem that way if we look at
thing from an imperative point of view.
5:20
But let's take a second
to break this down.
5:25
Now, this is a common mental hurdle, so
5:27
let's take a gander at the imperative
printing style over here.
5:29
In our expression, we are joining two
expressions with a double ambersand,
5:34
meaning that this must be true and
this must be true.
5:39
As you probably know,
Java will optimize or
5:44
short circuit the expression if
this first one here is false.
5:47
It will never run this one, because they
both need to be true in order to continue.
5:51
So if we look at this stream
code here with a bad assumption,
5:56
that these are working
in an imperative way.
6:01
Again, this is not what is happening but
it's a common misconception.
6:03
It seems like this line here
is gonna be expensive, right?
6:08
It's gonna take all of the Oregon ones and
then pile them up and
6:12
then do the next one, the next filter,
and then it does it again.
6:15
Now, imperatively, it would seem like we
made some sort of new data structure that
6:19
returns that and so on but wait,
this isn't what is happening.
6:23
Really what is happening is
these methods are chained or
6:28
fused together into a pipeline.
6:31
You need to visualize these intermediate
operations like this filter,
6:33
these two as a single
fused together method.
6:37
So here, try this.
6:42
Imagine we have this list of jobs,
and imagine it being, well,
6:43
just like one of those marbles that we
talked about dropping into the stream.
6:47
So here, let's do this.
6:50
Let's set up some fake data here.
6:51
So let's say that we have a job
that's in Louisville Kentucky.
6:54
And a job that is in Bend Oregon.
7:01
So we're gonna do this one at a time,
just one at a time.
7:05
So that's the thing to remember here.
7:09
When you look at these streams,
it's one by one,
7:10
the job's gonna go through the pipeline.
7:13
So the first one comes through one by one.
7:15
The first one is Louisville.
7:19
Louisville, Kentucky, it comes in,
the first job comes in.
7:21
Let's drop that marble comes in,
the job, does it equal Oregon?
7:23
No, it does not.
7:28
Bloop, it gets discarded.
7:29
Okay?
7:31
So it's sort of the same as
the short circuiting, right?
7:32
This is false.
7:35
Why keep going?
7:35
Why keep going to this next one?
7:36
It doesn't need to.
7:37
So it's gone.
7:38
The next one comes in, and it's for
Bend, Oregon, and it drops through.
7:40
Drop that marble through.
7:43
The first one is true, right?
7:44
Then it moves down to the next one.
7:48
Is it not this one?
7:49
And then it discards it.
7:50
Now, if that didn't make sense,
rewind me a bit and watch it again.
7:52
We're going to build on these concepts.
7:56
And I wanna make sure that you understand
that these intermediate operations
7:59
are a pipeline that you pass each of the
items through from the source one by one.
8:03
Not all at once.
8:08
So I'm gonna refactor this,
I'm gonna highlight.
8:09
And I'm gonna choose extract method.
8:15
And we're gonna say printPortlandJobs,
8:19
we'll call it Stream Cool,
8:23
and let's just run it make sure that,
that still works, awesome.
8:29
So the way this works we're
gonna keep these methods around.
8:33
So you can kind of see the difference
between the imperative and
8:36
the declarative style.
8:39
And feel free to explore around.
8:40
So that's looking pretty good, right?
8:42
So not only does the method on each
line look more maintainable, right?
8:44
Each one of these methods
on its own line.
8:48
You can also comment parts out like this.
8:50
So let's image that I wanted
to see all jobs in Oregon, so
8:53
I could comment out this
intermediate operation really easy.
8:57
So then I'm gonna go ahead and run it.
9:01
And we'll see here that there's some
stuff in Beaverton and Hillsborough,
9:07
which are bordering.
9:11
See, look I can get this job here
at Nike headquarters in Beaverton,
9:13
a bordering city to Portland.
9:17
So let's take a look at these two
on the screen at the same time.
9:19
So these are pretty similar, right?
9:24
Now, a common need for
filtering is to produce a subset of items.
9:27
Here we're just printing them out.
9:31
Let's practice some more filtering
right after this quick break.
9:32
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up