1 00:00:00,600 --> 00:00:03,870 Okay, raise your hand if you ever received a null pointer exception. 2 00:00:05,060 --> 00:00:07,110 I see, every single one of you. 3 00:00:07,110 --> 00:00:10,000 Now keep your hands raised if you are ever happy about that happening. 4 00:00:11,130 --> 00:00:11,630 Nobody. 5 00:00:13,015 --> 00:00:16,940 Null pointer exceptions happen when you attempt to access a property or 6 00:00:16,940 --> 00:00:21,530 a method on an object, and that object is in fact not there, it's null. 7 00:00:21,530 --> 00:00:25,390 So of course you can call a method like, get first name on nothing. 8 00:00:25,390 --> 00:00:27,790 So a runtime exception is thrown. 9 00:00:27,790 --> 00:00:30,220 And you track the error through the code 10 00:00:30,220 --> 00:00:32,510 to find out that it's possible that the object, 11 00:00:32,510 --> 00:00:35,900 the one that you so confidently trusted in being there, actually isn't. 12 00:00:37,040 --> 00:00:40,130 So how do you know that the value might not be there? 13 00:00:40,130 --> 00:00:41,540 Well, that's a great question. 14 00:00:41,540 --> 00:00:44,610 And the simple answer is this, you actually don't. 15 00:00:44,610 --> 00:00:49,010 You have to trust your API designer won't return a null or 16 00:00:49,010 --> 00:00:51,170 you have to be overprotective. 17 00:00:51,170 --> 00:00:53,880 You see this null protection all over the place in code. 18 00:00:53,880 --> 00:00:54,760 You know the difference. 19 00:00:54,760 --> 00:00:55,690 Is this thing null? 20 00:00:55,690 --> 00:00:56,770 If so, throw in an exception. 21 00:00:56,770 --> 00:00:57,980 If not, everything's cool. 22 00:00:57,980 --> 00:00:58,480 Let's keep going. 23 00:00:59,760 --> 00:01:04,170 Now because some of these terminal stream operations are known to maybe 24 00:01:04,170 --> 00:01:09,270 not return a value, Java 8 introduced a new class called optional. 25 00:01:09,270 --> 00:01:13,460 They are intended to be used as return values for methods only, and 26 00:01:13,460 --> 00:01:17,970 they represent the presence of a value or the absence of a value. 27 00:01:17,970 --> 00:01:21,540 Now this is a common concept in many programming languages, 28 00:01:21,540 --> 00:01:23,740 usually it's known as an option type. 29 00:01:23,740 --> 00:01:27,410 More frequently known as a maybe type in functional programming. 30 00:01:27,410 --> 00:01:28,930 Check the teachers notes for more information. 31 00:01:30,310 --> 00:01:33,950 By getting your hands on one of these optionals, you know very clearly that 32 00:01:33,950 --> 00:01:38,560 there is a possibility that maybe there isn't a value for you to access. 33 00:01:38,560 --> 00:01:41,730 Let's take a quick look at what we can do with optionals that are returned 34 00:01:41,730 --> 00:01:43,840 from these terminal operation. 35 00:01:43,840 --> 00:01:48,147 >> So we've seen that aggregates like max and min will return an option, 36 00:01:48,147 --> 00:01:51,289 because there's a chance that there are no items. 37 00:01:51,289 --> 00:01:53,520 Remember what's the max of nothing? 38 00:01:53,520 --> 00:01:56,860 So using a similar thought process let's write in, 39 00:01:56,860 --> 00:01:59,575 I'm feeling lucky style search of the job titles. 40 00:01:59,575 --> 00:02:04,028 Now that's that google style of search where you just return the first result 41 00:02:04,028 --> 00:02:06,921 whose job title contains a specific word, okay? 42 00:02:06,921 --> 00:02:08,500 So let's write the search first. 43 00:02:08,500 --> 00:02:10,600 So that would look like we have a stream, right? 44 00:02:11,830 --> 00:02:14,530 And we'll just use a simple filter, right? 45 00:02:14,530 --> 00:02:18,740 So we'll say filter, we'll say where the job, 46 00:02:18,740 --> 00:02:24,050 where the getTitle contains Java. 47 00:02:26,150 --> 00:02:27,490 To make that whatever later. 48 00:02:27,490 --> 00:02:31,310 So there's a terminal operation called findFirst which 49 00:02:31,310 --> 00:02:33,260 returns the first item that is found. 50 00:02:34,910 --> 00:02:36,560 Just like it says. 51 00:02:36,560 --> 00:02:40,209 okay, so let's use the intention action here and let's see what it creates. 52 00:02:40,209 --> 00:02:44,876 So we'll introduce a local variable, and it creates an option of jobs and 53 00:02:44,876 --> 00:02:46,922 we're gonna call it foundJob. 54 00:02:46,922 --> 00:02:53,820 Now let's go ahead and let's print that out, so we'll print out foundJob. 55 00:02:54,860 --> 00:02:59,140 Cool, so the first job that I found is from Business Intelli Solutions in Frisco, 56 00:02:59,140 --> 00:03:00,220 Texas. 57 00:03:00,220 --> 00:03:03,776 It's a junior Java job plus QE role. 58 00:03:03,776 --> 00:03:04,605 That sounds fun. 59 00:03:04,605 --> 00:03:07,010 QE being Quality Engineer. 60 00:03:07,010 --> 00:03:12,780 All right, so see how the job variable is inside of an optional. 61 00:03:12,780 --> 00:03:15,760 Now that's because the value is present. 62 00:03:15,760 --> 00:03:21,610 In fact, there is a method on the optional that lets us see if it is in fact present. 63 00:03:21,610 --> 00:03:22,366 So let's do that. 64 00:03:22,366 --> 00:03:28,350 We'll say foundJob and this is an optional, isPresent. 65 00:03:28,350 --> 00:03:32,520 And if you want to get the value out of an optional, you can just call get on it, so 66 00:03:32,520 --> 00:03:36,220 we'll say .get. 67 00:03:36,220 --> 00:03:40,150 And there so true, and you'll see that it's no longer wrapped there. 68 00:03:40,150 --> 00:03:43,360 But what happens if the value isn't there? 69 00:03:43,360 --> 00:03:44,660 So let's see. 70 00:03:44,660 --> 00:03:48,150 Java is across just about every industry that I can think of. 71 00:03:49,300 --> 00:03:50,740 So let's see if I can break it. 72 00:03:50,740 --> 00:03:56,960 I want the Java job in the trampoline industry. 73 00:03:56,960 --> 00:03:59,700 So if we run it, boom. 74 00:03:59,700 --> 00:04:04,920 See how the isPresent is false, and it's attempting to get an empty optional, 75 00:04:04,920 --> 00:04:08,270 throws a NoSuchElementException. 76 00:04:08,270 --> 00:04:10,850 Which is more or less a null pointer exception. 77 00:04:10,850 --> 00:04:15,940 So as you can imagine you can deal with this optional in an imperative way, right? 78 00:04:15,940 --> 00:04:21,090 I mean I could hypothetically put this get here inside of an if statement. 79 00:04:21,090 --> 00:04:24,780 And I can check first to see if it's present, just like our null pointer dance. 80 00:04:24,780 --> 00:04:28,710 But as you can probably imagine by now, the optional 81 00:04:28,710 --> 00:04:32,420 actually has some great declarative approaches to the problem space. 82 00:04:33,430 --> 00:04:37,740 So let's do this, let's go ahead and turn this into a method. 83 00:04:37,740 --> 00:04:42,140 So we probably wanna have a variable, so let's extract this variable out first. 84 00:04:42,140 --> 00:04:44,015 Let's do this. 85 00:04:44,015 --> 00:04:45,590 So I'm gonna use the action head. 86 00:04:45,590 --> 00:04:50,860 I'm gonna say extract variable, [LAUGH] and it wants to call it trampoline. 87 00:04:50,860 --> 00:04:51,860 Let's call it searchTerm. 88 00:05:02,679 --> 00:05:03,530 Let's do that again. 89 00:05:04,820 --> 00:05:11,000 So I'm gonna take this trampoline and I'm gonna refactor and extract the variable. 90 00:05:11,000 --> 00:05:12,870 I want the variable to actually go outside. 91 00:05:12,870 --> 00:05:15,690 So let's go ahead, we'll say that that's fine, but I'm gonna move this up here. 92 00:05:16,790 --> 00:05:20,260 And now we don't need this anymore, we don't need this, let's see if this will 93 00:05:22,520 --> 00:05:25,310 swing it to single lambda, there we go. 94 00:05:25,310 --> 00:05:30,101 And it's called, we want this called search terms, 95 00:05:30,101 --> 00:05:33,830 and then we'll choose refactor rename. 96 00:05:35,770 --> 00:05:40,636 And a rename code occurrences to searchTerm. 97 00:05:40,636 --> 00:05:41,470 Here we go. 98 00:05:41,470 --> 00:05:46,180 And then we wanna turn this whole thing here into a method. 99 00:05:47,500 --> 00:05:48,618 So let's do that. 100 00:05:48,618 --> 00:05:53,050 Let's do refactor and we'll say extract method, 101 00:05:54,080 --> 00:05:57,600 and we will call this LuckySearchJob. 102 00:05:59,870 --> 00:06:03,396 And yeah it's gonna take jobs and it will take the search term, okay? 103 00:06:07,449 --> 00:06:11,849 And if we switch this back to Java, I'm gonna do a run, 104 00:06:11,849 --> 00:06:14,540 cool, see it's still working. 105 00:06:16,600 --> 00:06:21,572 So now that we're returning this search, we can go ahead and 106 00:06:21,572 --> 00:06:24,760 we will say, make this an if. 107 00:06:24,760 --> 00:06:27,560 So we'll say, if foundJob isPresent. 108 00:06:28,610 --> 00:06:36,870 Now we are safe to use the get here Right, so we can safely use the get. 109 00:06:36,870 --> 00:06:38,970 So that is what the null dance looks like. 110 00:06:38,970 --> 00:06:43,300 Because we know that this is gonna be here, 111 00:06:43,300 --> 00:06:45,670 we can go ahead and chain off of the outside of it. 112 00:06:45,670 --> 00:06:47,150 So we know because it's present. 113 00:06:47,150 --> 00:06:48,650 So now I can use getTitle. 114 00:06:49,970 --> 00:06:52,760 And if I run this, there we go, 115 00:06:52,760 --> 00:06:56,440 we'll just see that it is printing out the title there. 116 00:06:56,440 --> 00:06:58,730 So if we take a look at this intention action here, 117 00:06:58,730 --> 00:07:00,590 it's gonna suggest something that's kind of nice. 118 00:07:00,590 --> 00:07:01,770 This is the declarative side. 119 00:07:01,770 --> 00:07:06,204 It says replace optional is present with ifPresent. 120 00:07:06,204 --> 00:07:07,560 So let's go ahead and do that. 121 00:07:07,560 --> 00:07:09,978 So ifPresent takes a consumer, right? 122 00:07:09,978 --> 00:07:13,960 It takes a consumer, a consumer does this, and this returns to nothing. 123 00:07:13,960 --> 00:07:15,700 See how it takes whatever value's passed in. 124 00:07:15,700 --> 00:07:19,390 This job here, this will only be called if it's present. 125 00:07:19,390 --> 00:07:21,470 Otherwise, nothing will happen. 126 00:07:21,470 --> 00:07:24,200 So again, let's go ahead, let's switch this back to trampoline. 127 00:07:27,000 --> 00:07:30,280 We run and nothing happens. 128 00:07:30,280 --> 00:07:34,910 But sometimes you want to return a value like if there isn't a value there at all. 129 00:07:34,910 --> 00:07:39,040 Like in the case maybe I wanna show no job found for instance. 130 00:07:39,040 --> 00:07:41,990 So let's look at this imperatively first. 131 00:07:41,990 --> 00:07:46,390 Let's switch this back to where we were. 132 00:07:46,390 --> 00:07:47,280 So that's imperatively. 133 00:07:47,280 --> 00:07:55,634 So maybe, I would like to say, else, No jobs found. 134 00:07:55,634 --> 00:08:03,448 Let's run that and then let's run trampoline, right? 135 00:08:03,448 --> 00:08:05,770 And so it's gonna hit the other branch. 136 00:08:08,586 --> 00:08:09,330 No jobs found. 137 00:08:10,510 --> 00:08:14,270 So declaratively, options have some really nice methods. 138 00:08:14,270 --> 00:08:15,590 So here, check this out. 139 00:08:15,590 --> 00:08:21,370 Let's get rid of all of this and we're gonna print out, foundJob. 140 00:08:21,370 --> 00:08:28,775 Now this is an optional and optionals have a map method, so let's do .map. 141 00:08:32,863 --> 00:08:34,820 And it works just like streams. 142 00:08:34,820 --> 00:08:37,580 So we're gonna pass in a method reference here. 143 00:08:37,580 --> 00:08:42,110 So it's gonna get the title off of that job should it exist. 144 00:08:42,110 --> 00:08:47,270 And just like we had before in the else, there's a method called orElse 145 00:08:47,270 --> 00:08:52,070 which sounds a little over the top like orElse. 146 00:08:52,070 --> 00:08:53,920 And then you'd have the value that you'd like to show. 147 00:08:53,920 --> 00:08:55,660 So you say, No job found. 148 00:08:57,390 --> 00:09:00,340 Cool, so once again if you get rid of this and 149 00:09:00,340 --> 00:09:03,760 you try to run it It's gonna say optional empty, right? 150 00:09:03,760 --> 00:09:06,000 Because there's nothing for it to do there. 151 00:09:06,000 --> 00:09:10,950 But if I drop the orElse, and 152 00:09:10,950 --> 00:09:12,940 I don't know why this isn't lining up it should be lining up. 153 00:09:17,127 --> 00:09:17,740 No jobs found. 154 00:09:22,470 --> 00:09:25,360 There are a bunch of different functional approaches to dealing with 155 00:09:25,360 --> 00:09:27,430 optionals which make them quite nice. 156 00:09:27,430 --> 00:09:29,830 But it's also a bit misunderstood. 157 00:09:29,830 --> 00:09:31,596 Check the teacher's notes for more information. 158 00:09:31,596 --> 00:09:36,486 So the main trick to remember with optionals is that if you're going to go 159 00:09:36,486 --> 00:09:40,574 the imperative route and you call get yourself, remember, 160 00:09:40,574 --> 00:09:43,313 always check to see if is present first. 161 00:09:43,313 --> 00:09:46,873 Otherwise you'll end up causing the equivalent of that null pointer exception 162 00:09:46,873 --> 00:09:48,980 that we've all learned to not love. 163 00:09:48,980 --> 00:09:50,850 All right, so let's take a quick break and 164 00:09:50,850 --> 00:09:55,940 then swing back to take a look at how to let streams self generate for us.