This course will be retired on June 1, 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
Preview
Start a free Courses trial
to watch this video
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