1 00:00:00,420 --> 00:00:03,430 All right, we now have a list of Java jobs. 2 00:00:03,430 --> 00:00:06,840 I'd like to figure out which of those jobs are here in Portland where I live. 3 00:00:07,930 --> 00:00:11,070 I'm sure every single one of those jobs aren't here in town, so 4 00:00:11,070 --> 00:00:14,270 I'll need to filter out the ones in Portland Oregon. 5 00:00:14,270 --> 00:00:18,250 So let's take a quick second and solve the problem imperatively first, and 6 00:00:18,250 --> 00:00:19,370 then we'll get declarative. 7 00:00:20,570 --> 00:00:23,450 So this is a pretty common ceremony that we need to do, right. 8 00:00:23,450 --> 00:00:26,451 So I'm gonna get rid of this line here. 9 00:00:26,451 --> 00:00:30,462 So what we need to do is loop through these jobs, right. 10 00:00:30,462 --> 00:00:35,430 So we say for (Job job : jobs), right, this jobs that was passed in. 11 00:00:35,430 --> 00:00:39,270 And let's see, if the job, so 12 00:00:39,270 --> 00:00:43,780 there is a thing here called getState() and I need to see Oregon, and 13 00:00:43,780 --> 00:00:48,640 Oregon is OR not to be confused with or. 14 00:00:48,640 --> 00:00:52,284 We wanna look at everything words in Portland, so 15 00:00:52,284 --> 00:00:56,120 we wanna get where the job state is Oregon and the city 16 00:00:58,615 --> 00:01:04,910 equals("Portland"), okay. 17 00:01:04,910 --> 00:01:07,210 So, we're gonna open that if block and close that and 18 00:01:07,210 --> 00:01:08,720 then we wanna print that out, right. 19 00:01:11,210 --> 00:01:13,540 So, that's gonna print all of the jobs that are in Portland, Oregon. 20 00:01:13,540 --> 00:01:14,150 Let's run that. 21 00:01:15,640 --> 00:01:19,630 Okay, so we've got like, five jobs that were posted here in the last day. 22 00:01:19,630 --> 00:01:20,650 Now, note, 23 00:01:20,650 --> 00:01:24,600 this is the results of the toString method that's in the job class here. 24 00:01:24,600 --> 00:01:28,930 If we go take a look at Job, there's a toString method here. 25 00:01:28,930 --> 00:01:29,820 So that's what's going on. 26 00:01:29,820 --> 00:01:31,090 That's what this mess here is. 27 00:01:33,900 --> 00:01:37,160 So now, let's refactor this into a method of itself. 28 00:01:37,160 --> 00:01:40,050 So we can keep it around for reference, so I'm gonna come up and 29 00:01:40,050 --> 00:01:46,790 choose Refactor this and I am going to choose Method. 30 00:01:46,790 --> 00:01:51,419 And we will make this a private method, and 31 00:01:51,419 --> 00:01:56,058 we're gonna name it printPortlandJobs. 32 00:01:56,058 --> 00:01:59,990 Imperatively, I'm gonna say, okay. 33 00:01:59,990 --> 00:02:00,970 And it'll take a list of jobs. 34 00:02:02,360 --> 00:02:04,930 So now, we can come back and take a look at what we had before. 35 00:02:04,930 --> 00:02:09,010 So, now, let's do this declaratively, right? 36 00:02:09,010 --> 00:02:12,100 So there's several ways to create streams from our data but 37 00:02:12,100 --> 00:02:15,180 most collections offer a new stream method. 38 00:02:15,180 --> 00:02:15,860 Let's call it. 39 00:02:15,860 --> 00:02:16,860 So we have jobs, right? 40 00:02:16,860 --> 00:02:18,630 So jobs is a collection, it's a list. 41 00:02:18,630 --> 00:02:19,660 We're gonna say stream. 42 00:02:21,680 --> 00:02:23,680 Okay so what did we want to do? 43 00:02:23,680 --> 00:02:27,110 Yeah, we want to filter the jobs that are in Portland, Oregon. 44 00:02:27,110 --> 00:02:31,815 So now, quite intuitively we just say that we want to filter the stream. 45 00:02:31,815 --> 00:02:34,655 So we say .filter. 46 00:02:34,655 --> 00:02:38,935 As you can see, it takes a predicate, which was the function shape that we saw 47 00:02:38,935 --> 00:02:43,275 that takes an item, and then returns a boolean a true or false. 48 00:02:43,275 --> 00:02:47,605 So the way that the filter method works is if the predicate returns true, 49 00:02:47,605 --> 00:02:49,570 it will keep the item. 50 00:02:49,570 --> 00:02:53,180 So the item in this case is going to be a job. 51 00:02:53,180 --> 00:02:55,100 So why don't we name our parameter job? 52 00:02:57,409 --> 00:03:00,060 And remember, it's gonna figure out the type, right? 53 00:03:00,060 --> 00:03:03,510 It's gonna know that it is of type job, just by the way it's working. 54 00:03:03,510 --> 00:03:04,550 Pretty cool, right? 55 00:03:04,550 --> 00:03:09,270 Because it's only one parameter, I don't need the parenthesis In the body of 56 00:03:09,270 --> 00:03:14,490 the lambda will be to get the state and see if it equals Oregon, right. 57 00:03:14,490 --> 00:03:20,810 So we're gonna say job.getState().equals("OR"). 58 00:03:20,810 --> 00:03:23,550 Now, remember this equals method returns a true or 59 00:03:23,550 --> 00:03:28,090 false and automatically the return statement is assumed. 60 00:03:28,090 --> 00:03:30,230 So it's gonna return true or false. 61 00:03:30,230 --> 00:03:32,170 It's gonna return whatever this is. 62 00:03:32,170 --> 00:03:35,370 So let's introduce some manners early, here on. 63 00:03:35,370 --> 00:03:38,530 Now, filter is an intermediate method. 64 00:03:38,530 --> 00:03:41,510 Now, remember that each call to these intermediate methods 65 00:03:41,510 --> 00:03:44,580 is going to return a stream, so that you can chain them together. 66 00:03:44,580 --> 00:03:47,990 And these get pretty long pretty quick. 67 00:03:47,990 --> 00:03:52,420 So typically, each of these are written on a line all their own. 68 00:03:52,420 --> 00:03:54,190 Now, it's a little strange looking at first but 69 00:03:54,190 --> 00:04:00,280 I promise you, if you see them written all out in one line you will go "rude". 70 00:04:00,280 --> 00:04:02,310 And fix it, just like this. 71 00:04:03,793 --> 00:04:05,350 They pile up pretty quick. 72 00:04:05,350 --> 00:04:08,160 Now, speaking of which, let's add another filter here. 73 00:04:12,332 --> 00:04:13,679 So we need to get the city, right? 74 00:04:13,679 --> 00:04:18,440 So we'll do job, we're gonna do job.getCity, 75 00:04:18,440 --> 00:04:21,420 we'll say equals Portland. 76 00:04:23,900 --> 00:04:27,205 So, now we have two intermediate operations, 77 00:04:27,205 --> 00:04:30,690 now we need to add a terminal operation. 78 00:04:30,690 --> 00:04:34,010 So, very similar to how iterables provide a forEach method, so 79 00:04:34,010 --> 00:04:35,330 does the stream interface. 80 00:04:35,330 --> 00:04:40,406 So let's do that, forEach, and 81 00:04:40,406 --> 00:04:47,031 then we're gonna use our method reference to print line on System.out. 82 00:04:47,031 --> 00:04:52,320 So System.out and we'll just get to print line here so 83 00:04:52,320 --> 00:04:54,540 we'll print each one of those through in I need a semicolon. 84 00:04:55,580 --> 00:04:58,500 Okay, so we are gonna run this code, let's take a look. 85 00:05:02,005 --> 00:05:05,630 And, boom, it works, same five jobs. 86 00:05:05,630 --> 00:05:08,060 Now, did anything in that feel weird? 87 00:05:08,060 --> 00:05:10,530 Were you wondering why we made two 88 00:05:10,530 --> 00:05:13,580 filter statements instead of one expression like we did here? 89 00:05:14,960 --> 00:05:20,340 Does writing two methods here feel like we are doing extra unnecessary work? 90 00:05:20,340 --> 00:05:25,480 Now, it does seem that way if we look at thing from an imperative point of view. 91 00:05:25,480 --> 00:05:27,630 But let's take a second to break this down. 92 00:05:27,630 --> 00:05:29,830 Now, this is a common mental hurdle, so 93 00:05:29,830 --> 00:05:34,020 let's take a gander at the imperative printing style over here. 94 00:05:34,020 --> 00:05:39,140 In our expression, we are joining two expressions with a double ambersand, 95 00:05:39,140 --> 00:05:44,450 meaning that this must be true and this must be true. 96 00:05:44,450 --> 00:05:47,350 As you probably know, Java will optimize or 97 00:05:47,350 --> 00:05:51,470 short circuit the expression if this first one here is false. 98 00:05:51,470 --> 00:05:55,490 It will never run this one, because they both need to be true in order to continue. 99 00:05:56,800 --> 00:06:01,040 So if we look at this stream code here with a bad assumption, 100 00:06:01,040 --> 00:06:03,388 that these are working in an imperative way. 101 00:06:03,388 --> 00:06:08,540 Again, this is not what is happening but it's a common misconception. 102 00:06:08,540 --> 00:06:12,290 It seems like this line here is gonna be expensive, right? 103 00:06:12,290 --> 00:06:15,860 It's gonna take all of the Oregon ones and then pile them up and 104 00:06:15,860 --> 00:06:19,290 then do the next one, the next filter, and then it does it again. 105 00:06:19,290 --> 00:06:23,780 Now, imperatively, it would seem like we made some sort of new data structure that 106 00:06:23,780 --> 00:06:28,060 returns that and so on but wait, this isn't what is happening. 107 00:06:28,060 --> 00:06:31,060 Really what is happening is these methods are chained or 108 00:06:31,060 --> 00:06:33,580 fused together into a pipeline. 109 00:06:33,580 --> 00:06:37,730 You need to visualize these intermediate operations like this filter, 110 00:06:37,730 --> 00:06:42,190 these two as a single fused together method. 111 00:06:42,190 --> 00:06:43,500 So here, try this. 112 00:06:43,500 --> 00:06:47,580 Imagine we have this list of jobs, and imagine it being, well, 113 00:06:47,580 --> 00:06:50,400 just like one of those marbles that we talked about dropping into the stream. 114 00:06:50,400 --> 00:06:51,750 So here, let's do this. 115 00:06:51,750 --> 00:06:54,720 Let's set up some fake data here. 116 00:06:54,720 --> 00:07:00,070 So let's say that we have a job that's in Louisville Kentucky. 117 00:07:01,670 --> 00:07:04,090 And a job that is in Bend Oregon. 118 00:07:05,130 --> 00:07:07,540 So we're gonna do this one at a time, just one at a time. 119 00:07:09,150 --> 00:07:10,730 So that's the thing to remember here. 120 00:07:10,730 --> 00:07:13,580 When you look at these streams, it's one by one, 121 00:07:13,580 --> 00:07:15,490 the job's gonna go through the pipeline. 122 00:07:15,490 --> 00:07:19,340 So the first one comes through one by one. 123 00:07:19,340 --> 00:07:21,140 The first one is Louisville. 124 00:07:21,140 --> 00:07:23,740 Louisville, Kentucky, it comes in, the first job comes in. 125 00:07:23,740 --> 00:07:28,400 Let's drop that marble comes in, the job, does it equal Oregon? 126 00:07:28,400 --> 00:07:29,610 No, it does not. 127 00:07:29,610 --> 00:07:31,720 Bloop, it gets discarded. 128 00:07:31,720 --> 00:07:32,410 Okay? 129 00:07:32,410 --> 00:07:35,410 So it's sort of the same as the short circuiting, right? 130 00:07:35,410 --> 00:07:35,970 This is false. 131 00:07:35,970 --> 00:07:36,640 Why keep going? 132 00:07:36,640 --> 00:07:37,940 Why keep going to this next one? 133 00:07:37,940 --> 00:07:38,910 It doesn't need to. 134 00:07:38,910 --> 00:07:40,090 So it's gone. 135 00:07:40,090 --> 00:07:43,780 The next one comes in, and it's for Bend, Oregon, and it drops through. 136 00:07:43,780 --> 00:07:44,900 Drop that marble through. 137 00:07:44,900 --> 00:07:46,880 The first one is true, right? 138 00:07:48,080 --> 00:07:49,420 Then it moves down to the next one. 139 00:07:49,420 --> 00:07:50,420 Is it not this one? 140 00:07:50,420 --> 00:07:51,270 And then it discards it. 141 00:07:52,400 --> 00:07:56,940 Now, if that didn't make sense, rewind me a bit and watch it again. 142 00:07:56,940 --> 00:07:59,010 We're going to build on these concepts. 143 00:07:59,010 --> 00:08:03,120 And I wanna make sure that you understand that these intermediate operations 144 00:08:03,120 --> 00:08:08,870 are a pipeline that you pass each of the items through from the source one by one. 145 00:08:08,870 --> 00:08:09,960 Not all at once. 146 00:08:09,960 --> 00:08:12,460 So I'm gonna refactor this, I'm gonna highlight. 147 00:08:15,105 --> 00:08:19,678 And I'm gonna choose extract method. 148 00:08:19,678 --> 00:08:23,620 And we're gonna say printPortlandJobs, 149 00:08:23,620 --> 00:08:29,156 we'll call it Stream Cool, 150 00:08:29,156 --> 00:08:33,760 and let's just run it make sure that, that still works, awesome. 151 00:08:33,760 --> 00:08:36,070 So the way this works we're gonna keep these methods around. 152 00:08:36,070 --> 00:08:39,020 So you can kind of see the difference between the imperative and 153 00:08:39,020 --> 00:08:40,130 the declarative style. 154 00:08:40,130 --> 00:08:42,490 And feel free to explore around. 155 00:08:42,490 --> 00:08:44,320 So that's looking pretty good, right? 156 00:08:44,320 --> 00:08:48,520 So not only does the method on each line look more maintainable, right? 157 00:08:48,520 --> 00:08:50,890 Each one of these methods on its own line. 158 00:08:50,890 --> 00:08:53,720 You can also comment parts out like this. 159 00:08:53,720 --> 00:08:57,010 So let's image that I wanted to see all jobs in Oregon, so 160 00:08:57,010 --> 00:09:01,020 I could comment out this intermediate operation really easy. 161 00:09:01,020 --> 00:09:02,310 So then I'm gonna go ahead and run it. 162 00:09:07,512 --> 00:09:11,489 And we'll see here that there's some stuff in Beaverton and Hillsborough, 163 00:09:11,489 --> 00:09:13,470 which are bordering. 164 00:09:13,470 --> 00:09:17,550 See, look I can get this job here at Nike headquarters in Beaverton, 165 00:09:17,550 --> 00:09:19,670 a bordering city to Portland. 166 00:09:19,670 --> 00:09:24,630 So let's take a look at these two on the screen at the same time. 167 00:09:24,630 --> 00:09:27,110 So these are pretty similar, right? 168 00:09:27,110 --> 00:09:31,370 Now, a common need for filtering is to produce a subset of items. 169 00:09:31,370 --> 00:09:32,880 Here we're just printing them out. 170 00:09:32,880 --> 00:09:35,600 Let's practice some more filtering right after this quick break.