Java - Lambda Expressions & Functional Programming in Java 8 (Java SE 11 Developer Certification) | Go1bn Media | Skillshare

Playback Speed


  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

Java - Lambda Expressions & Functional Programming in Java 8 (Java SE 11 Developer Certification)

teacher avatar Go1bn Media, Java Developer | AWS Certified

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

17 Lessons (1h 42m)
    • 1. Introduction

      0:38
    • 2. Course Overview

      1:37
    • 3. Understanding Lambda Expressions

      2:29
    • 4. Live Code - Understanding Lambda Expressions with an Example

      7:19
    • 5. Introducing Functional Interface

      3:33
    • 6. Live Code - Why Functional Programming with an Example

      10:28
    • 7. Syntax of Lambda Expressions

      3:42
    • 8. Recipe - Implementing a Functional Interface - Step by Step

      8:10
    • 9. Live Code - Local Variables in Lambda Expressions

      11:20
    • 10. Handling Exceptions in Lambda Expressions

      6:17
    • 11. Understanding Method References

      6:34
    • 12. Understanding Functional Interfaces In Depth (Slide)

      3:37
    • 13. Important Standard Functional Interfaces

      3:16
    • 14. Live Code - Practical Examples of Standard Functional Interfaces

      7:04
    • 15. Live Code - Practical Examples of Standard Functional Interfaces Part 2

      11:16
    • 16. Functional Composition

      8:09
    • 17. Primitive Types - Specialized Functional Interfaces

      6:10
  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

20

Students

--

Projects

About This Class

This course will teach you everything you need to know about lambda expressions and Functional Programming in Java so that you are ready to use them for your work and to prepare you to successfully pass the Oracle Java SE 11 Developer Certification exam.

Meet Your Teacher

Teacher Profile Image

Go1bn Media

Java Developer | AWS Certified

Teacher

Hey, I am Sazz, The Founder of Go1bn Media.  Go1bn Media is a Creative Web Design & Digital Marketing agency.

We offer various digital marketing and website designing services - Web Design & Development, Keyword Research & Competitor Analysis, Email Marketing, Search Engine Marketing (SEM), Search Engine Optimisation (SEO), Social Media Marketing, Graphics Design.

We have designed websites and have run many Digital Marketing campaigns for more than 100 clients, varying across all industries.

At Go1bn Media, We believe in sharing our knowledge. Here on skillshare, I am going to empower you all with our amazing classes.

 

See full profile

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Introduction: Hi, I am sadly and welcome to my course getting started with lambda expressions in Java, I have created this course with my 10 years of experience working as a Java developer in several Fortune 500 companies and building several restful web services, streams and lambda expressions are core features of modern Java programming. So it's really important for you as a Java developer to understand them. Streams and lambda expressions are also subjects that you need to understand for the Oracle, java is 11 developers certification exam. So without further ado, let's get started. 2. Course Overview: Hey guys, welcome to the course getting started with lambda expression and functional programming in Java. Now let's look at the course structure. This course is divided into two modules. The first module is getting started with lambda expressions, and the next module is working with functional interfaces are in the first module, we will first understand what is lambda expression. Next, we will solidify our understanding about Lambda expressions with an example. Next, I will introduce you all to functional interface to clear some misconceptions, we'll also see what is the difference between anonymous class and lambda expression. Next, I'll explain why functional programming with an example, we will then explore all the possible syntax of lambda expressions. Next, I will provide you all a simple recipe to implement any lambda expression. From here on, we will discuss some advanced topics such as capturing local variables in lambda expressions, this and super keyword in lambda expressions and handling exceptions in lambda expressions. Finally, we will end this module with understanding method references. In the next module, we will understand functional interfaces in depth. We will then explore the important standard functional interfaces available in the JDK. Next, we will see some practical use cases of standard functional interfaces. Next way you will understand functional composition. Finally, we'll also look at some specialized functional interfaces. The only prerequisite for this course is you should have a basic knowledge of Java and any ID for Java programming. So we have plenty to cover. So without further ado, let's get started. 3. Understanding Lambda Expressions: Hey guys, Welcome back. So let's first understand what lambda expression is really about. What is lambda expression? The first thing that you absolutely need to understand and remember is the following. Lambda expression implements a functional interface. And this is absolutely a key point. And if there is one thing that you want to take away from this course is this definition that lambda expression implements a functional interface, right? This is a very important point that you have to remember all through this course. And I'll repeat this again and again in this course. Now you may have heard and read all over the internet that lambda expression is actually a way of writing instances of enemy must class, but it is not, right. Lambda expression is not another way of writing instances of an animal's class. If you already know what entity must class is, then you would know that an anonymous class may implement any kind of interface, not necessarily functional. And it can extend any kind of class, whether it is a concrete or an abstract class. And we'll see what a functional interface is in the next lesson. But for now, remember that anonymous class can implement any kind of interface, not necessarily functional. And it can extend any kind of class, whether it is a concrete class or an abstract class, right? So lambda expression is very different from most classes. And if you want to just remember one definition, I want lambda expression. I'll repeat again. Lambda expression implements a functional interface. Now another way to look at lambda expression, or you can say another definition of lambda expression is Lambda expression is an anonymous method. Okay? So why does animals method? Because we just defined it on the fly and it doesn't have a name, right? And it implements the functional interface. So, you know, so lambda expression is an anonymous method that implements a functional interface. Now coming to functional programming, right, in functional programming, the idea is that we can create code or a function just like data, and that we can pass a piece of code or function to another method. And this is the main concept of functional programming and lambda expression help you to adopt functional programming style in Java. Now in the next lesson, we will see some live code and understand lambda expression with an example. 4. Live Code - Understanding Lambda Expressions with an Example: Okay, so welcome back. It's time to see some live coding and understand lambda expressions with an example. So let's jump onto the intermediate code editor and see some light code. So here I am in my intermediate code editor. And before I begin, I'll just give you an overview of the project structure that we'll be working with in this course. And I'll explain you the dataset that we'll be playing around with all through this course. Okay, So what we have here is inside the Columbian dot data package. We have the data that we'll be working with. So we have an employee object. Now, the employee object, basically it contains the fields name, age, department, salary. And then we have a constructor through which we are initializing the fields. And then we have our set of getters to get those fields. And then we are overriding the toString method to format the string as per our need. And then we have overridden the equals and hashCode method, which is pretty simple. So in short, employees that Poggio object with all these fields. It also has something called department, and the department is nothing but an enum here we have defined for departments, finance, digital, sales and marketing department. We have something called employee data, where we have a list of employees and we have a getter get employees to get the list of implies. So pretty simple and straightforward, right? And we'll work with this data a lot also this course. Okay, so now let's get started with our first example of lambda expression. Okay, So for that I have created a plus lambda expression example 001, and we have a main method inside which will be coding everything in this. Listen, okay? Right, So what are we going to code, right? So our problem statement is that we want to print all employees sorted by salary. So let's get started. Okay, so the first thing that we'll do is obviously we want to get the list of employees. So let's get the list of employees. So pissed off employees. List of employees is equal to, we can say list of employee, employee data dot git implies. So this will give us the list of employees. And let's now sys out. Let's just do a sys out here, say employee list. Okay? And now here what we'll do is we'll just look through the list and print the employees. Pretty simple. Okay? So employee, employee to look through the employee list. And what we'll do is we'll do a sys out of all the employee. Okay, if I just run this now, what we can see is it just prints the employee list right, along with the age, which department they belong to and the salary. Okay? Now, obviously what we wanna do here is we want to sort this list BY salary. So let's solve that. And if you know sorting in Java, what we do is we use, we want on the list, we can do a sort, okay? And what this sort excepts is comparator interface that we need to implement basically, yeah, so we need a comparator implementation here, right? What do we need to do here is we'd introduce new comparator. What we're doing is we're just providing implementation for the interface comparator here. And we're overriding the compare method. And by default it is just returning 0. Obviously, we want to sort by salary. So what we'll do here is return 0 to 1 dot get salary.com to 0, two dot get salary. Okay? So this is what it is going to return. And now, once this is sorted, if we again print, let me just copy this and try to print this again. And what I want to do is now employ list. I want to write here sorted. Okay, So this is a sorted list and I'm just now again printing. So let me just try to run this again. And as we can see that we have to list. One is, we're printing as it is, and the next list is sorted. Okay, As for the salary. Now, why am I even showing you this right? Why am I even showing you sorting here? Okay. The reason I'm showing you is this is a very old style of doing it in Java. We can do now using lambda expression. Interesting part is if you just hover over this, the IntelliJ idea itself is telling you that enemy months, new comparator can be replaced with Lambda. Okay, so we can actually with a single click, this kind of old implementations can be refactored with lambda using your code editor, be it Eclipse or IntelliJ it, you can do that, right? I just want to show you how that code would look like if I replace with Lambda, okay? So you can see that this block of code is replaced with a single line of code. So we had how many lines? Five lines of code, it is replaced with a single line of code with lambda expression. Okay, So now this gans seemed like some kind of a magic, but it's very interesting. But at the same time, this can be very confusing to understand what is really happening over here. Here, the lambda expression that we're seeing here is nothing but a implementation of the function interface. And the functional interface in this case is nothing but the comparator you've just got to compare it to here, we can see that competitor is indeed functional interface. And we'll see in detail what is a functional interface in the next lesson. But right now, just understand that in this example, this single line is actually implementing the functional interface comparator. And it is providing an implementation to the abstract method of that comparator interface. And the abstract method is nothing but the compare method, okay? And what we're doing here is this two parameters are matching with ploy, O&M employee or two. Okay. So it is matching to employ one and employee o2. And we're just returning int by comparing the salary of 0, 1, and 0 to L. Explain you in the upcoming videos how to write this kind of expressions, this kind of Lambda expressions in detail. So what we've done in this lesson is we have just simply created a lambda expression with the help of intelligent. Okay, So what I'll do is I'll just comment out the previous old way of doing in Java. I'll just see if this new code that we've written with the help of lambda expression is working properly. So let me just execute this program again and check the output. And as we can see that we have successfully sorted the employee list with the help of lambda expression. So that's it. In this video, we just simply created a lambda expression with a hilltop IntelliJ idea. In the next lesson, I'll explain you what a functional interface is. And then from there on, I'll show you how functional interface is actually helping us achieve the functional programming in Java and why functional programming is so important Java. So thanks for watching and see you in the next lesson. 5. Introducing Functional Interface: All right, welcome back. Okay, So now what is a functional interface? So there are only two words in the functional interface, right? And that is functional interface and that's it, right? So it is not very complicated to understand what is a functional interface. A functional interface is an interface in Java, right? So we already know what is an interface in Java. A functional interface is an interface in Java. That's the first, the next point is, what makes an interface a functional interface? This is very important. The functional interface has only one abstract method. So this is the only criteria for an interface to be a functional interface. That a functional interface has only one abstract method in it. Okay? And what is the lambda expression? Lambda expression implements a functional interface, okay? So in this slide, one thing that you have to pay attention to it the second, that a functional interface has only one abstract method and it can have many non-abstract method in that interface, but it can only have one abstract method. Now, if you are new to these Java 8 world, right, post Java 8, I will say, then you might be aware that now in interface we have the default methods. So when I say non-abstract methods, I'm referring to those default methods. So an interface can have many other non-abstract methods. But the criteria for any interface to be functional interface is that it has to have only one abstract method. Yeah, sorry for repeating it again and again. But this is very important. So next is comparator interface, which is an example of functional interface. Now white is a functional interface because it has only one abstract method and the method is nothing but the compare method here, which returns int and compares two objects. In the next slide, we can see that this is a functional interface and this is implementing that functional interface with the help of an animus Class patient. And this is the way of doing it in lambda expression. This might tempt you to believe that, okay, planned expression is just another version of anonymous class, but that is not true, as I've explained you in the lesson 1, that an anonymous class need not always implement functional interface. But lambda expressions always implements functional interface. Whenever you see any lambda expression, it is actually implementing a functional interface. Now there are many functional interfaces in Java, right? And these interfaces existed even before this functional interface was introduced in the JDK, right? And we have the famous interfaces that comparator, then we have the Runnable interface, then file filter interface, and then the ActionListener interface. All these interfaces existed before even functional interface was introduced in Java. Now, after it was introduced, this interfaces automatically became constrained to face why? Because all these interfaces have only one abstract method defined in it. And that's the only criteria for becoming a functional interface. Okay, Now apart from these very popular functional interfaces, newly there were many functional interfaces introduced in the java.util package, which we will see in the next module of this course. So just to recap, a functional interfaces, any interface in Java that has only one abstract method. That's the point you have to remember all through the scores. 6. Live Code - Why Functional Programming with an Example: Okay, so now that we know what is a lambda expression and what is a functional interface, let me show you in this lesson why functional programming is so important with an example. Okay, so let's jump onto the intelligent code editor and see some live coding. Okay, so now I am in the integer code editor. What I'll do is I'll just create a new, I'll just create a new example. Let's call it 02. And let me get rid of everything from here. And what is the problem statement here? The problem statement is very interesting. Let's assume that your manager just walks up to you and ask you to write code that print the employees whose salary is less than salary limit, okay? So this is the requirement that we'll be working on, right? So we have to print all employees whose salary is less than the salary limit. Now you might have realized, oh, this is a very simple problem, too cold and you're straight away, just start coding, right? So let's do that. Okay, So let me call, create a method, right? Let's call it private static. Let's call it print employees. Okay. Please print employees. And what do you wanna do here is maybe say a list of employee, employee list. And obviously we want to give a salary limit, so we can say Salary, salary limit, okay? Right. So what are we going to do in this method is we're going to print out the employees whose salary is less than the cell, the limit. Okay. But that what I'll do is I'll just look through all the employee list. Its employee, employee leaves. It's just a simple for loop. And we will do is here. We'll say if p dot get salary, employee salary is, let's say, greater than, less than 0. And then we'll just do quintile in employee, sorry. Okay, So what we're doing here is we're just looping through the employee list and we're just printing the employees whose salary is less than the seller limit. This is absolutely fine. There's no problem with this. What we'll do here is of course we will just here. What do we need to do is we'll say list of employee. And let's just fetch all the employees former employee data. Okay? And then let's do print employees. Let's pass the employees here. And along with the employees, what do we need to do is sell a limit. So as a new big decimal, Let's say this is the limit, okay? So now if I just try to run this program, you can see it has actually printed all the salaries which are less than this salad limit, which is good, right? But the thing is, in software, I mean nothing is constant, right? So what happens is the next day your manager walks up to you and says, Okay, so as you have to write another program, and this time you have to print the employees which you're greater than the salary limit I need to who is getting the maximum salaries, right? And then, okay, so here's early that is interesting, that is quite easy for me to do. What you will do is we'll say print employees. So you'll just copy, paste this code and write other code. And here what we'll do is we'll do print employees less than, let's call it that. And let's say this is greater than, right. And here you'll just change it and obviously will just refactor this. So instead of print. And Let's call and the one, and let's call this as greater than, okay? So it didn't take much time to actually write this code, right? So what I'll also do to make it clear, which is greater than and less than is, I'll just call it as less than. And the next one. Greater than, okay? I have a list which is spinning the less than and a greater than. So let me execute this now. Okay? So here I have less than five people or less than that, and they're around six people who are earning more than that self-limit and which is good. But if you just see this program, this two methods exactly look the same, except this line. Right? Now what this is telling us is that if we could have just passed in this piece of code, then we could have actually reuse the entire function instead of writing this new method again, right? And that's exactly what functional programming is all about, right? That we should be able to passing some function as a parameter which can be used inside another method or function, right? So let's see how we can improve this code. Okay, So what I'll do is I'll create a basically it's clear interface, okay? And let's call it as employee filter. Okay? And in this employee filter, this is just an interface. So we'll just have a single abstract method. Okay, so that's it. Alright, so we just have a single abstract method inside the interface. So that qualifies for a functional interface. So as per the definition of company Interface, a functional interface is an interface that has only one abstract method in it, okay? Right, and so if it's the first interface, we can very well annotate with functional interface. And this is a notation does not make it a functioning deficits with, even without this notation, it is actually a function interface, right? Right, so this is a functional interface right? Now. How do we use it, right? So what do we can now do is I'll just copy paste this method again. And this time I'm writing a very generic method. I will just rename it to, let's say, print employees. And instead of giving the salary limit here, what I'll supply here is actually the employee filter. So I'll say employ filter, filter, okay? Now, this filter is something that I want to pass in here and then call the filter dot test method. And let's say employee, okay? So if, if it just passes that test and then, you know, it will, it just prints employee right? Now, what I've done here is I have just created a filter and I don't know what that filter is because I have not implemented that filter. But I'm just passing that as a parameter. And so this, this piece of code is now present inside this method, but the implementation is still not. They're actually right, we've never implemented it. Now. So how do I implement this? So this is a functional interface now. So which means I can actually create a lambda expression for this. Okay, so let me show you how that can be done now. So how that can be done is in the print employees, and I can pass in employees. And now here is where I define this field. Oh, how do I define this filter? Defining this filter is very easy. We all have to do is apt to provide an implementation for this method. This method, it just takes an employee object and returns a boolean. Okay? So what I do here Is it just takes an employee object and we have good salary.com two. And then we have to just gives sellers limit, which is nothing but near out big decimal, let's say greater than 0, right? What I've done here is I'm just printing the salaries which are greater than 0. Same thing I can do now here for the list and as well. Okay, and I'll just comment out the previous code. So now if I just try to print this, what happens if I just try to run this? It still runs, right? And we have, sorry, I've just, this should be less than, right? And if I just run the code now, and we have here the less than and greater than still works, fine. But if you just pay close attention to it, we have just not duplicated the code. So we have a single method that is handling both the use cases, print employees whose salary is less than the no cellular limit, and print employees whose salary is greater than the salad emit. Why? Because we are actually implementing the functional interface and the runtime. The advantage of functional programming is that we avoid code duplication in our code and we have actually in a single method that handles both this use cases. So I hope I have motivated you enough to explain why this functional programming is so important in Java and why you should actually learn functional programming. And it just opens the door for many possibilities in Java now. Okay, so in the next lesson we'll do a deep dive and also look at the Lambda expression syntax. What are the different syntax possible in lambda expression? Thanks for watching and see you in the next video. 7. Syntax of Lambda Expressions: All right, We'll come back. Okay, So now that you have seen what lambda expressions and functional interfaces are, it's time to deep dive into the details. Let's first take a closer look at the syntax of lambda expression. Let's compare the syntax of normal method with the syntax of a lambda expression. And normal method consists of a number of elements, an optional access specifier. Then we have the return type and then the name of the method, parameter list, and then the body, right? This is what a normal method looks like and this is how an lambda expression looks like. Since a lambda expression is an anonymous method, it has similar elements but with a slightly different syntax. A lambda expression consists of a parameter list and followed by an arrow symbol, which is written as a dash, followed by a greater than sign, and then the body. Now lambda expressions are not part of a class, so they don't have an access specifier. And since a lambda expression is an anonymous method, it obviously also doesn't have a name. You don't specify the return type of lambda expression explicitly, and you don't have to specify the types of the parameters. The compiler already knows what the parameters and the return types are because they are specified by a function interface that the lambda expression implements. For example, this lambda expression implements interface comparator and it's compared method takes two objects, employee and employer to and returns an integer. If you really want to, you can specify the types of the parameters, but this is normally not necessary. If you do, they must obviously match the types of the parameters specified the functional interface, otherwise you will get a compiler error. Now, why now lambda expression has no parameters. You use an empty pair of parenthesis before the arrow. You will do this. For example, if you implement interface Runnable with the lambda expression, the run method of interface Runnable takes no parameter. Finally, when a lambda expression has exactly one parameter, you can leave out the parentheses, but only if you don't specify the types of the parameter explicitly. This is a special case rule to make the syntax just a little bit cleaner for single parameter lambda expressions. Now the body of the lambda expression has two possible forms. Is either a single expression or a block between curly braces. Let's take another look at our first example. In this example, since we have only one line of expression, we can shorten this by removing the curly braces. And if you need more code in your Lambda expression, then single expression, then you will have to use a blocks in text just like this. Okay, So just to recap, a lambda expression implements a functional interface with the help of numerous method. A lambda expression consists of a parameter list, an arrow symbol, and the body. And the parameter types are optional. If there are no parameters, use empty parentheses. If there is single parameter, parentheses are optional. For multiple parameters, parentheses are mandatory. Body can be a block or a single expression. For the single expression, the curly braces are optional. So these are the basics of the syntax of lambda expression. There's too much information in this slide. So I would request you to pause this video here and go through this slide again. Thanks for watching and see you in the next lesson. 8. Recipe - Implementing a Functional Interface - Step by Step: Hey guys, welcome back. So now that we know what is a functional interface, we know what is the lambda expression. And we also have seen syntax of lambda expression. So now with those concepts, now in this video, I'm going to give you a simple recipe that you can follow to implement any functional interface and write your lambda expression. So this will be a very easy recipe that you can follow till you become expert in 19 lambda expressions. So we can implement a functional interface in just three easy steps. The first thing is you have to just look at the functional interface. And just after looking at the functional interface that you are going to implement, have to supply the parameters accordingly. And then the step 2 is Europe to use this arrow symbol, you can call this as a Lean arrow symbol, not a fat arrow symbol. And then the third step is you have to provide implementation to that method and return a valid return type. So I'll show you exactly what I mean by this three steps. But as of now, just remember that you have to supply the parameters then followed by the arrow symbol and then your body or the implementation of that method. Okay, So these are the three simple steps that you can follow for implementing any function interface. Now here in this slide, we can see a functional interface comparator. And why does the function interface? Because it has only one abstract method in it. And the RefSeq NO3 is compare method that accepts two object and returns the value int. So if we want to implement functioning to face first, what we need to do is we need to first, in step one, supply the parameters. And in this case the parameters are that it accepts two objects. And here in this case we're passing two objects, employee O1 and O2. And then we have the arrow symbol as the step two, and then followed by you have the body or the implementation of that method. Now this is your own business logic. So this implementation will be your own implementation, whatever your implementation is supposed to be, as per the use case. But this is basically the body, right? And what is important is this implementation short return int, right? Because here the return type is int, right? So three things that you have to remember is first you have to supply the parameters followed by the arrow symbol, and then providing the implementation of the body of the lambda expression, the return type should match to the return type of that abstract method that you are implementing. So I'll show you quickly with some live code so that you get used to this three simple steps. Okay, so let me quickly hit onto the intermediate code editor and show you how you can easily implement a functional interface. Okay, So I'm now in my code editor, and this is where we left off the last time we had retained so far in this course two examples, the lambda expression example 0, 1 and 0 2. Now, what I'll do is I'll create another example. So first thing is, as the use case of this example is the same like print all employees sorted by salary, right? So let's say you want to print all employees. Okay? So how do you print all employees? So we have actually on the employees list and on the list interface we have for each method using which using this forEach method actually you can print all the employees, right? So what is forEach method? Accepts is a consumer. If I just go to this forEach method, you can see that it accepts something called a consumer, right? And when I click on this consumer, it says that consumer is a functional interface, right? Okay, So if it is a function interface, the first thing that you need to figure out is what is that abstract method in that function interface. And this is their abstract method in that functional interface that you actually need to provide implementation for. Okay? Okay, so I'll go back to our example now. So what do we need to do is we need to provide implementation for that functional interface. Okay? So if you just see the consumer interface again, it says that it accepts an object t and it returns void edge, it doesn't return anything. So as per our recipe, the first step is supply the objects, supply the parameter. Okay, so what do we need to supply here is we need to supply here something called, you can say, let's call it employee E, okay? And this is what we need to supply actually, right? And it returns void, right? So you can just give implementation, right? So what we did is step one was that we need to supply parameters. Step two was made to put this arrow symbol and then provide some implementation for that method, right? Somebody, and this code compiles fine, right? Obviously this is of no use. Tell you provide some implementation in it, right? So we can say your system dot out dot insulin, and we can say employee E. So we did it in three steps. First is we supplied the parameter employee object, followed by the arrow symbol, and then the body of that. Now, if you have followed the lambda expression syntax, we can actually simplify this, right? There is only one parameter we can like get rid of this parenthesis and make it just like that when this compiles, right? And since there is only one single statement inside this body, right, there's only a single line. So we can also get rid of this curly braces and we can make it in a single line. So this is how we can implement it. We did it in three steps. Now I'll show you another example. Let's say I need to now sort the employees by salary. So what that, what I need to do is I can say Employees dot there is something called salt. So it's the same drill again, we need to follow the same steps that I showed you. So for this form, thermally actually need to supply something called comparator. So if you just go to this for implementation, it accepts something called comparator. And if you just go to the comparator, it, you can see that this is again a functional interface. We just need to check what's that abstract method that we need to implement. In this case, the abstract method that we need to implement is this that accepts two object and returns the value int. So what I'll do is I'll write here employee y1, comma employee E2, okay? And then followed by the arrow symbol. And then I just need to provide the implementation. Obviously this will not compile. Why? Because it's missing return statement. We actually need to return some integer, right? So let's say if you return one, it will actually compiled, right? So this code is actually compiling. Why? Because we have supplied to objects that it requires, followed by the arrow symbol. And then we're returning the correct return type, which is one. But obviously, this will not help you in sorting because we're actually not comparing two objects for which what we need to do is we actually do in sort by salary. So we need to compare the salaries, right? So Let's do that now. So you can say E1 dot you have Salary.com to, right? And then we can say E2 dot get salary. And we can say here, return, okay? So when you were a beginner, you can actually keep in mind those three steps and do it this way step-by-step for supply the parameters. And then followed by the arrow symbol. And then you just give the implementation, right? And then now, once you get used to it, you can actually then start simplifying this syntax, right? We know that first of all, the parameter types are optional, so we can remove the parameter types from here. Okay, so this compiles fine. And the next thing that you can do is since this is just a no single statement. So we can again get rid of this and then also get rid of this return statement, okay? And obviously we don't need this, okay? And then you can make it in a single line, and this is how it looks. Okay, so just to recap, first step is supply the parameters followed by the arrow symbol. And then you just need to implement the method and return the valid return type. That's the three-step that you need to follow for writing any lambda expression in Java. So that's all in this video. Thanks for watching and see you in the next video. 9. Live Code - Local Variables in Lambda Expressions: Hey guys, welcome back. In this video, I'll show you a very important concept in lambda expressions that is about capturing variables in lambda expressions. And now this is a very important concept, not only from the exam point of view, but also you should know this to understand how lambda expression actually works behind the scenes. Okay, this is a very important concept. So stay with me, I'll explain you step-by-step everything that you need to know about capturing variables in lambda expressions. So the first thing is that lambda expressions can use variables defined in an outer scope, right? So the variables defining the outer scope that is outside the lambdas patient, lambda expressions can use those variables. That's the point number 1 that you need to remember. The next thing is, so lambda can capture the static variables, instance variables, and also the local variables. That's the second thing that you need to remember. The third thing which is very important and you need to remember is that local variables must be final, are effectively final. Okay? So I'll show you exactly what I mean by that. But as of now, just remember that the local variables must be final or effectively final. Now to make things clear, I will just show you this is an example. So let's jump onto the intelligent code editor and see the all of this concept with an example. So here I am in my integer coordinator and what I'll quickly do is I'll just take reference of this example 0 to like from where we just left off. I'll just start from there. So what I'll do is I'll just clone this example 0 to, let's say copy and just paste it, and let's name it as example 04. And what I want to show in this example is that variable used in lambda expression must be final or effectively final. Okay? So this is what I want to show you. The variable used in lambda expression must be final or effectively final. This is the main objective of this exercise. So we'll see that right. So before that I'll just clean up this unused methods that we don't need, okay? Right, so we saw that in example 2, this is how we were printing employees, right? And we just get rid of all this commented code. So this is where we are, right? So let's just understand this concept that variable used in lambda expression must be final or effectively finally, so what we'll do here is, so let's say we define a local variable in a salary limit. Okay? So we define a local variable salary limit. And let's say we want to refactor this code. And we have created a local variable salary limit. And obviously then we can pass this celery limit over here, right? And we can pass it over here. Okay? Now this is absolutely fine if I just run this code and we can see that this Elvis or less than the cellular limit and this L is greater than the salary limit, right? Which is perfect. Now let's say that I want to assign another value to this cellular limit and it doesn't compile if you just see, now, it says that the variable used in lambda expression should be final or effectively final, right? What does it mean, right? What it means is that the variable that you're using inside the lambda expression should be final or effectively final, right? So it means either it should be final, which means if I make it final, I cannot actually, again, assign any variable because it is final variable, right? And that's how it works in Java. So now you'll get another compilation error saying cannot assign a value to final variables in our salary limit, right? But if we just remove this, right, then it throws compilation error at this point that variable used in lambda expression should be final or effectively final. What we mean by effectively final is that the, if you don't assign or if you don't change the value of that variable. That is also fine for the compiler because this variable is effectively final. So the compiler is smart enough to understand that you're not changing the value of this variable in your code. So which is, which means that even though you've not define the variable as final, that variable is effectively final. That's what it means by effectively final. Okay, so one thing that you have to remember is that local variables that you define in the outer scope, right? And that you supply to lambda expression should be final or effectively final. And this behavior is not only true if you supply it, It's the after that lambda expression, before the invocation of the Lambda expression. If you supply it even then this does not compile, right? So the bottom line is the local variable that is being used in lambda expression should be final or effectively final. Now let me show you another example before this concept becomes crystal clear. So now what I'll do is I'll change this use case a bit. So instead of, let's say, printing the employees for salaries live in salary limit. Let me say that our manager just wants to know how many employees are. Actually earnings salaries was less than the salary limit on how many employees are earning salary more than the seller intimate, right? So in short, this is what the count of the employees that don't want to know the name of the employees. So if that's the use case, then in that case, what do we need to do is we can, let's say, you know, implement one more method. Let's call it count employees. So we have something called count employees. We have employee list and imply Filter and it should return the count of the employees, right? So it should return something called int. Now let's just try to implement this in the functional style, you know, so instead of iterating through this for loop, what we will instead do is we can say employee list dot h. And what the forEach method accepts is consumer. That's something we have seen in the last previous example, right? So what we'll say is that For each, we just need to know supply, employee, object, employee, and we just need to filter out the employees, right? So we need to actually count the number of employees like so obviously this will not compile. So for that what we'll do is create another list employee and let's say filtered employee list, right? And this will be a new era list. Okay? So we have something called filtered employee list. So instead of printing will just try to add this to the filtered employee list. And then once everything is actually added, and then finally what we'll do is we'll say return filtered employee list dot size. Okay? So we have just written a new method for counting the employees based on this filter. Okay, so now our manager is obviously not interested in printing the employees. They just want to know the count of the employees. So what we'll do is we'll just count the employees. We can just change the sprint employees to count employees. Now the counter employees actually return the count of employees. So we need to just do a series out of it, right? So now if we just run this program, we can see that it is returning the count, right, less than 56, right? So we have six employees with sellers get a salary limit and file employees whose salary is less than this elder limit, right? So this is perfect. The one thing that I just explained you a while ago is that the local variable that you define in the lambda expression final are effectively final and you cannot change that variable inside the lambda expression. But if you just look into this method, I have a filtered employee list and I'm actually adding employees everytime to that list. So you might not think that I'm actually then changing this list every time and how this is compiling. Well, the reason is compiling is, so I'm actually not changing the object that this variable is referring to, right? So this variable is still referring to the same object, which means I have not violated that rule, that this variable should be fine. All right, so this variable is final and it is referring to the same object. It's just that, I'm just mutating that object, right? I'm just adding some new employee to that list. And this list is, as you know, it is a mutable collection basically, right? So what I'm all I'm doing is I'm just mutating the state of that object, but this variable is still pointing to the same object. So that is why this code is compiling. Now, even though this code is compiling, and you should be happy that it is compiling, right? There's no problem with it. And now just to highlight a drawback of this kind of implementation, I'll just quickly show you one small example before we end this lesson. So what I'll do is I'll just convert this employee list to something called stream for now, don't bother too much about what is streamed. Already days, I've just converted this collection employee list to stream, and I'm just iterating through this stream using the same forage. So nothing much has changed. If I run this, it will compile fine. We can see that it's returning actually the same result, right? So this is fine, right? But let's say that tomorrow you have a huge collection of, let's say, 1 million employee list. And obviously, if you have a huge list, doing this sequentially is not a good idea. And that is where the concept of parallel streams comes into picture. So we have something called parallel streams. Now in Java, this will now look through this collection in a concrete manner and obviously improve the efficiency of this program, right? So what I did is I just converted this employee list into parallel stream. And if I just run now, you can see that it's running fine. If I just run multiple times, I just ran a couple of times and nothing happened. What I'll do is I'll just go to my this collection for the time being, increased, this list to show you that how this will actually break when your data is huge. So let's say you have this data, okay, for the time being. And if I just run this now, you can see that already output is returning is different and then you'll get this exception array index out of bound exception. So as you can see that this code is actually not consistent and it is behaving intermittently with different results because we have parallel streams and in parallel streams, what happens is this code is now running concurrently. So that is when this code will not work, there is a side-effect of mutating variables inside lambda expression. So there's a better way you can do it now with the help of streams and lambda expression. So all we need to do is employ list, then you know, the parallel stream. And then instead of writing the implementation, you can actually make use of the method filter, right? All we need to do is we need to just pass in the predicate, which is nothing but employ filter. And obviously employ filter will not work because it's actually our own implementation and it's not a predicate. So let's make it as a predicate first. So we just met it as a predicate. So let's call it as an employee predicate. And this is the filter, right? So all we need to do is pass in this filter employed predicate as of now, for understanding purpose, we can supply this predicate. And then on top, after supplying the particular, we can call this count method. And that will actually count the number of employees. And then we can actually return it from here. And the final one, final change that we need to raise it returns long. So let's make this as a long instead of int. Okay? That's what we have effectively done in this single line, is we have first filtered the employees and then we are counting the employees and all using the built-in methods that are present on the stream. So now if I just run this, we can see that it is very consistent and every time it returns the same value. So in short, what we saw in this lesson is that lambda expression can use variables defined in an outer scope. Lambda expressions can capture static variables, instance variables and local variables. Then the last point which is very important is local variables must be final or effectively final. And then we saw some side effects when you try to mute it objects inside the lambda expression, which you should avoid in your program. So that's what in this video, thanks for watching and see you in the next video. 10. Handling Exceptions in Lambda Expressions: Hey guys, welcome back. In this video, I'll talk about handling exceptions in lambda expressions and we'll see how to handle exceptions in lambda expressions with a practical use case. So let's jump onto the integer code editor and get started. Okay, so now I am in my integer co-teacher. And so let me just quickly create a new example for this demo. So what I've done is I've just quickly created our new example file for this demo. For this demo, the use case is, let's say your manager just asked you to print the list of employees, not in the console, but let's say in a file. So that's the use case that we'll be working on in this example, with the help of that example will understand how to handle exceptions in lambda expression. Okay, So now getting started with this use case, what do we need to do is we need to print the employees in a file, right? So first, let's try to get the list of employees, okay, and this we have seen in the past just imply data dot get employees. So now what we need to do is we need to actually write it in a file, right? So for that, let's use the file writer class and let's call it as a writer, new FileWriter. And let's give it a file name. Let's call it employee underscore list, dx d. Okay. So this is the file that we will be printing all the employees to, right? Obviously if you just see the compilation error, it says unhandled exception Java IOException, right, and which is fine, so we have to handle this exception. And what we can do is obviously we can just use try with resources block to handle this exception. So let me do that. Let's just try to catch this exception because it's a checked exception, right? So we'll call it as IOException and let's say system.out.print line, and let's just print the message. Okay, So what we're doing is we have just created FileWriter Class 2, which will write all our employee objects. So what we'll do is we'll just look through all the employees so we can say employee, employee and look through all the employees. And obviously we just want to print all the employees, right? So what we'll do is we'll say Writer dot, right? And we just want to say employee dot toString. And let's create a new line for every employee's, right. So if you just run this code now, yep. And as we can see that a new employee list dot TXT file is created and we can see that it is printing fine, right? Right, so we are writing this to a new TXT file, all our employees, which is great. And this is how we can do with the old for each loop. Because now that we know lambda expression, let's try to refactor this code with lambda expression. Okay, So what do we can also do is instead of doing it this way, we can actually just do Employees dot forEach. What do we need to do now is to this follow-up h, We can just say for every employee, just write the employees to the file. Okay. This is the new way of doing it. I'll just get rid of the old way of doing it. So this is, this is how you can do it with the help of lambda expression. Now if you just see this line right, it is actually not compiling and it's saying unhandled exception Java dot IOException. So we are again getting this exception even though we've handled it here, but it throws exception inside the lambda expression. And why it throws exception is because to just recall from our last classes, what we have understood from our last classes is that lambda expression always implements a functional interface. And that functional interfaces, you can call it also as an anonymous method, right? So what this functional interface is actually implementing here is a consumer interface. And if you see a consumer interface, the Except method actually doesn't throw any exception. And that is the reason this lambda expression is actually not throwing an exception. And that is where it says unhandled exception Java dot IOException. And which is surprising because we think in the old way, we didn't get any error. But if when you try to do the same implementation in the, using the lambda expression, you will get this compilation error. So how do we deal with this problem? Obviously, one thing that we can do is fit me, change it to a block. So here what we can do is now I can actually surround this without try-catch inside the lambda expression, the inside the body, I can just try to handle this I, and this works fine. So what we've done is we're now actually catching the exception inside the lambda expression. And this is fine, right? But what happens is, if you recall, the main purpose of lambda expression was to write less code. It right? That was the main purpose of lambda expression so that you can write simple code, easy to understand code in a single line most of the time, right? And if you just see here in this example, this is defeating the purpose of lambda expression because, because our old foreach loop contains actually lesser number of lines then this lambda implementation here, but this is the only way you can handle exceptions in lambda expression. Okay, So now let me just show you if this is working fine or not. So what we'll do is we'll just delete this file. Yep, So I've removed it and let's just run this again to see if this is working fine. Okay, So we have this file again here and we can see that the IT spending. So, so our lambda implementation is working fine and we're also handling the exception. So one thing that you can argue now here is like you are actually handling the IOException twice in this code. Now to avoid this kind of multiple exception handling, what we can do instead is we can actually, instead of catching the exception here, we can actually throw runtime exception, which is actually an unchecked exception. So what I'm doing is I'm just throwing some runtime exception, which is actually unchecked exception. And then in this code outside, I can actually catch the runtime exception and handle at one place, right? So this is actually one more pattern that you can follow that is actually catching the checked exception inside the lambda expression and throwing some unchecked exception and catching an unchecked exception in the outer catch block. Okay, So this is how you can handle exceptions in lambda expression. So in this kind of situations, you can actually decide whether the old forEach is better for you or the Lambda expression is better for you. Because if you see this quote here, the line number of lines you have written for the lambda expression is much more than the old implementation using the forage. So that's all you need to know about handling exceptions in lambda expression. Thanks for watching. See you in the next video. 11. Understanding Method References: Hey guys, Welcome back. The last topic we will discuss in this module is method reference. Method references are closely related to lambda expression. So this is a good moment to learn about them. Let's start right away with another example. Suppose that we want to print each employee in the list of employees. We can call forEach on the list of employees with a lambda expression that's simply calls system.out.print line on each employee. When we are calling the forEach method, we're giving you the method that it should execute on each of the elements in the list. The method that we're given here is an anonymous method in the form of a lambda expression, but this method is really just an extra unnecessary layer. The lambda expression here does nothing but call an existing method. So here we can get rid of this extra method call if we could tell for it that it should call him System.out.print a link directly. That is possible if we use a method reference, we can replace the lambda expression in this method by a method reference to the print Allen method of the System.out object, which looks like this. So remember, when a lambda expression does nothing but called an existing method, we can replace that lambda expression with a method reference. A method reference is just like a pointer to a method just like lambda expression, a method reference implements a functional interface and that is useful in situations like this example where you have an existing method that you can use. And of course, just as with lambda expressions, the method, the method reference points to must match with the method defined by the functional interface. The functional interface that forage takes is interface consumer, which defines an exit method that takes one parameter and has return type void, the quintillion method in the System.out object is defined in the class print stream and it takes one parameter and has the type void so it matches the execute method of the interface consumer. This in texts of method differences uses the double colon notation after the double colon is the name of the method that we want to refer to, which is printed in, in this example, a method reference can either refer to a static method and instance method or a constructor. And what you should write before the double colon depends on which of those types of method you want to refer to. Here is the list with an overview of four types for a static method, the method reference consists of a className, double colon, and the name of the method. For instance, methods, there are two types. A method reference to an instance method of a specific object has a reference to the object before the double colon and the name of the method after the double colon, a method reference to an instance method which is not for one specific object, the class name before the double colon. When such a method reference is used to replace a lambda expression, the method will be called on what would be the first parameter of the lambda expression. And finally, a method reference to the constructor has the class name before the double colon and the keyword new after the double colon. Now let's take a look at an example of each of the different types of method reference. First, let's look at the method reference for a static method. Let's add a static method is overpaid to our example class that takes an employee and returns true when the employee's salary is more than certain. Salary collections have a remove method which takes a predicate, which is one of the standard functional interfaces that you will learn about in the next module is overpaid method that we have just created matches the interface predicate. So we can pass it to the remove method with a method reference. For a method reference to a static method will put the name of the class that contains the method before the double colon. Next we have method reference that refers to instance methods. There are two types of method reference that referred to instance methods. We have already used one of them, the method reference to System.out.print Allen refers to the println method of a particular print stream object, which is the Princeton object that the variable System.out refers to. In this case, what's before the double colon is a reference to a particular object. The other type of method reference to an instance methods look like a method reference to a static method. So before the double colon is the class name, and in this case there isn't a particular object that the method should be called upon. For this example, we get a stream from the list of employees and then we can call a map on it. The map method transform elements of the stream for each element is going to call Lambda expression that you supplied to it. Suppose that here we want to extract just the name of the employees. We can write a lambda expression that calls the getName method on the employee. We will then finish this line with a call to forage. The whole line iterates over the list of employees, gets the name and pinch them. Now we can replace the lambda expression that we pass to the map method by method reference. Note that this method reference refers to the instance methods getName of class employee, but it does not refer to any particular employee object. The map method is going to call on each of the employee objects in the stream. Finally, method reference can refer to a constructor. One of the use cases of this is when you were using the factory design pattern. Let's add an interface employee factory with the create method that takes same parameters as the constructor of the class employee and that returns an employee object. We can now use a method reference to the constructor class of employee as the implementation of this interface, a method reference to a constructor has the name of the class before the double colon and the keyword new after the double colon, we can now of course call the create method on the factory, which in this case we'll just call the constructor of class employee. So those are the four types of method references. To summarize then, when a lambda expression does nothing but calling existing method, we can replace that lambda expression with a method reference. The method that the method reference points to must match with the method defined by the functional interface. And here are the four types of method references for a static method. The method reference consists of a class name, double colon, and the name of the method. For instance, methods. There are two types of method reference to an instance method of a specific object has a reference to the object before the double colon and name of the method after the double colon. A method reference to an instance which is not for one specific object, has the class name before the double colon. And when such a method reference is used to replace lambda expression, the method will be called on what would be the first parameter of the lambda expression. Finally, a method reference to the constructor has the class name before the double colon and the keyword new after the double colon. So these are the important things that you need to remember about method references. Hope I cleared all the concepts of method references in this video. Thanks for watching and see you in the next video. 12. Understanding Functional Interfaces In Depth (Slide): Hey guys, welcome back. In this video, let's understand functional interfaces in depth. In the previous module, I introduced functional interfaces to you all. In this video, we will understand functional interfaces in depth. So what makes an interface a functional interface? And there's only one thing that mix any interface, a functional interface. And that is, a functional interface has only one method. But you should note that having a single abstract method does not mean that the interviewers cannot have other methods. The functional interface can have static methods, default methods, or the methods inherited from the java.lang object. And please pay attention to the last point. That is, methods inherited from the java.lang.Object. And we've seen in the previous lecture that, you know, comparator is a functional interface. And if you just go to the Java documentation for the comparator interface, you can see that it has many methods, right? And if you just see it has many static methods. We have many instance methods which are nothing but all the default methods. And if you just go to F sigma thirds, you can see that there are actually two f sigma thirds, right? And that is where the last point that I was making is very important. It can also have the methods inherited from the java.lang.Object, right? And if you see here, this method is actually inherited from the object class. So this does not count. So that is where this point is very important, that a functional interface can have static methods, default methods, or methods inherited from the java.lang.Object. So the only criteria for any interface to be a functional interface is that it should have only one abstract method. And apart from this one abstract methods, it can have static methods, default methods, or methods inherited from the java.lang.Object. That's the only criteria. And if it satisfies this criteria, it is a functional interface. To next, the Java standard library contains a special annotation for functional interfaces. And that is nothing but the accurate functional interface annotation. And we have seen the functional interfaces and notated with this notation. But one thing you need to notice that the functional interface annotation is actually optional and it is not required to use this annotation on functional interfaces. So the main purpose of this notation is to express that an interface is intended to be used as a functional interface. So when an interface has a single abstract method, it is still a functional interface even when it's not annotated with this notation. Now having said that, when you do use this annotation, the compiler will check and validate if the interface is indeed a functional interface or not. So the annotation is not purely for documentation purposes only if you use this annotation on an interface which really isn't a functional interface, the compiler will actually report an error, right? So it is actually good if you use the annotation because then the compiler will check and validate and ensured that this is indeed a functional interface. This is a notation might sound similar to the override annotation that you can put on methods. And that annotation is likewise not required on methods that override methods from a superclass, but it's good practice to use it and it will make the compiler perform some useful extra checks. And the same thing applies to the functional interface with the help of this notation, the compiler ensures that the interface is indeed a functional interface, okay, and that's all you need to know about functional interfaces. In the next video, we'll look at some important standard functional interfaces that are available in the JDK. Thanks for watching and see you in the next video. 13. Important Standard Functional Interfaces: Hey guys, welcome back. The Java standard library contains a package java.util dot function that contains a set of functional interfaces for common use cases. So in this video, we will look at the important standard functional interfaces. You will use these functional interfaces a lot when you work with streams, we will start with the most general interfaces in this package, and then we will take a look at the more specialized interfaces. So one of the most fundamental functional interfaces in the package java.util dot function is the interface function represents an arbitrary function with one input and one output. It's abstract method is the apply method that takes one parameter for an arbitrary type T and returns the value of an arbitrary type are a common use case for this is when you need to transform values in some way will see a practical use case of this in the upcoming video. Next important interface is the consumer interface. Consumer represents a function that takes one input and has no output. It defines and accept method that takes one parameter of type T but has return type void. In other words, you can give a consumer and input of type T, but it only return anything you could say that it consumes its input. A consumer is often used as a final step in a sequence of operations where consumer does something with the final result. Next, the interface supplier is opposite of consumer. It, it takes a function that takes no inputs, but has one output. It defines a get method that takes no parameters, returns a value of arbitrary type T. So situations where this is useful are, for example, as a factory method or with lazy initialization. And other commonly used functional interface is the interface predicate, which represents a function that takes one input and returns a Boolean value. This is, for example, useful for filtering collections. You might remember that in one of the examples in the module about Lambda expressions, we wrote our own interface employee filter. That interface had exactly the same shape as the interface predicate. So we could have use predicate there instead of inventing our own functional interface. Now for the interfaces that you just learned about, there are also versions for functions that takes two inputs rather than one input. There is a bifunctional which represents a function with two inputs and one output. There is by consumer which represents a function with two inputs and no outputs. There's obviously no by supplier, because the supplier is by definition a function that takes no inputs. And Java does not support multiple return values right? Now, there is also a BY predicate, which is a predicate that takes two inputs. So it represents a function that takes two inputs and returns a Boolean. And that's the quick overview of the main functional interfaces of the package, java.util dot function. But if you want to know about all the interfaces available under the package java.util function. You can explore about T8 it using an ID or you can refer to the Java docs on Oracle website. Okay, so that's all in this video. Thanks for watching and see you in the next video. 14. Live Code - Practical Examples of Standard Functional Interfaces: Hey guys, welcome back, and it's now time to see some live coding, will see some practical examples of standard functional interfaces in this video. So let's jump onto our integer code editor and get started. Okay, so I'm now in my integer Chordata. What I'll do is I'll just quickly create a new class. Okay, so let's just create a new class, 0 6. So what I've done quickly is I have just created a new class and define a use case for this example. So the use case for this example is that we need to search employees and fit your salary. And in this example we'll see the tactical implementation of predicate function and consumer. So the use cases such employees and phage salary. Okay? So let's just try to write a very simple, you know, method. We'll say we want to search employees and returns an optional employee. Okay, So the method name would be, let's say Find employee. And what we would be passing to this is a list of employee employees. And obviously we'll be searching implies. So along with it, we'll be passing a predicate. And, you know, now what is a pretty good, pretty good. It helps you in filtering. They will see what is the predicate. It just accepts an object and returns a boolean, right? That's what is a predicate all about. Now, what we'll do here is we'll just look through the employees. And here, if predicate or test employee, right, we are going to return an optional of employee, right? And if it doesn't matches, which is going to return optional empty employees present, it just returns an optional of employee, right? This kind of design pattern is actually very useful because it helps you to avoid NullPointerException, right? Otherwise, what we would have done here is we would have written employee object and maybe we would have returned null here if there was no employee object found, right, and that actually causes NullPointerException. And we need to handle that null check in our code right here with the help of optional, we now know that okay, employee object is optional. Optional actually offers many other features that we'll see in a moment. Okay, what do we do here is let's say optional of employee. And let's call it as a, let's say employee. And now we can invoke this find employ method wherein we will pass the employees and also will pass a predicate, right? So we're searching by obviously the employee name. So what are, we can define it here is the Lambda function, right? And the, what we are implementing here is a predicate, right? So pretty good, accepts an object and returns a boolean, right? So we're just saying employee dot getName, dot equals, right? And here we can give that employee name, right, some employee name. So this is basically, you know, searching in the list of employees. And it is actually filtering out by the name right here, the name we've given it, Steve, what we can do here is we can say if employee is present, okay. If employees present, just print that employee. Okay. So you can say System.out.print, print, len, employee dot get. Okay. And as the use cases saying that in search and present phase cell, right? So we can just say Fitch, good salary, okay? So this is present is a method that optional is offering us. So optionally studying, okay, if employees present, then only do this. If employee is not present, we will not printing anything, right? Well, just try to run this now. Yeah. As you can see now, it is returning the salary. Obviously we can't borrow much better way, but this is a salvage, was just searching the employee and fitting this LV. If I give an invalid name, it would actually not print anything. Okay. It's not printing anything. All right, So this is what we can do, but we can do better than this, right? Because with the help of optional now, you can actually take functional programming to the next level, right? And that is where this concept is very important. And in your projects actually you should do it this way, right? So that's what we'll just see how you can now use the complete functional programming style in your while coding. Okay? So what we can do here now is on optional, okay, So we can say employee, which is an optional employee, we can say employee dot map. And in the employer may have, what we actually have is a function, basically write it accepts a function which is nothing but a mapper function, right? So here what we can now do after finding the employee, so we can actually map this employee noun to an employee salary, right? And this is where we're seeing the implementation of the function interface I. So here map accepts a function, okay? So we're just mapping the employee object to the salary and which is nothing but a big decimal, right? So you can say from the type employee we're actually mapping to a decimal and we're actually returning the salary. And then we can say, if present, okay, Again, this is accepting consumer and we know what is a consumer. Consumer accepts input and it doesn't return anything red is avoid. Okay? So here actually we'll do again, you know, system dot out, dot print line. You can see that we in a single line actually, we have done the mapping and then we're also, if it is present, we're actually printing that employee. Okay, so I'll say here that this is the old way, the old way implement. And this is using the functional style. Okay? Okay, so this is, I'll just comment this for the time being. And if I just change the name back to Steve again, right? And if we just run this, it prints the salary, right? And this time in the functional programming style. And obviously now that you know what is method reference, we can also change this to a method represent every IID normal Eclipse Intellij a beat any ID. It actually gives all the suggestions. Here. It's saying lambda can be replaced with message or friends. And indeed it can be, we're not doing anything. You're just accepting an object and we're just again passing that to another method. So obviously here, method references can be used. Similarly here also Method differences can be used because here also we're not doing any manipulation with just accepting the argument and passing an argument to another method, right? So both the places you can actually replace this function L lambda expression with method reference. So I'll just do that and I live in, change it here. So now you can see that we have actually implemented this Intel use case with a single line. And here we have used actually the particular functional interface. And then here we're actually doing a mapping using the function interface. And then if present here, we're actually passing the consumer. So in this video, I just explained you how you can actually use predicate function and consumer and write your programming entirely a functional programming style. Okay, in the next video, I'll show you another practical use case of the functional interfaces. Thanks for watching and see you in the next video. 15. Live Code - Practical Examples of Standard Functional Interfaces Part 2: Hey guys, welcome back. In this video we'll see another practical implementation of the standard functional interfaces that we have in JDK. Let's just jump onto the intelligent co-teacher and get started. Okay, so I'm here in my code editor and let me just create a new example for this use case. Okay, so what I've done is I have just quickly created a new example. And this is the use case for this example, right? The use case is that we need to group employees by each department and the functional interfaces that you'll be seeing in this video. We'll be mostly a function consumer and by consumer. And this is a very important use case because every project that you'll work on, you will mostly see this kind of use cases. So just stay with me and follow along this video. I'm sure this will be really exciting. First, what we'll do is I'll implement this use case group implies spice department in the old way, not in the functional way, right? And then in the second part of this video, I will show you how you can implement the same use case using the functional style so that you can compare and contrast between the functional style of programming and the, you know, the traditional way of programming in Java. If you see the use case that we have, right? It's pretty simple use case. You might have already done it. You're not only just follow along and I'll show you how to implement this, your scale, right? So the use cases group employees by department, okay, so let's define a new method. Let's call it employees. Employees by department. Let's pass in the list of employee to this. Okay? So we are passing the list of employees. So obviously we want to group the employees by his department, okay? Right, so let's now implement this. So first of all, what we need is whenever we have two group employees, right, we actually need a HashMap, right? So let's define our map. And the map would be a map of department. So where the department would be the key, right? And the the value would be a list of employee, right? So this is what let me also import the map. Okay. So what do we have is employee employees. Employees by department, okay. And let's use a HashMap for it, okay? Right? So what we've done is just we have created a new hash map. And the map we have the keys as department and the value will be a list of employees. How to do this in the old style, right prior to the functional programming was introduced in Java as we go through the list of employees. So let's just iterate through the list of employees. Okay? If we just iterate through the list of employees, and then we can say if, if the key is not present in the map, right? So if it doesn't contain the key, right, and what is the key? The key is nothing but your employee dot gave department, right? And we need to say that if if the key is missing, right, basically, then what do we need to do is we need to first put that key in the map, right? So we need to just put that key in the map. So we're just creating an entry in the map basically for that key, right? So it just kidding, will say that key is obviously your department and we should be doing a new ArrayList. Okay? I mean, when for the first time it finds any department, it will just create an entry for the department. And then what we can do is employ a department or obviously we have to get the entry. We have to get the get that entry. So it will be like employee dot get Department. This will actually give you the list of employee, right? And in that list we need to add this new employee. This is something you have done for ages in Java, you know, in the old style. Now we have the map ready right? Now, what we need to do is just we need to print the employees obviously. So we can say map dot entry, we can say department. And so we have a department and then we have what list of employee and this is just an entry and we will be looping through the map employed by department entry set. Okay? So what we're doing is we're just looping through the, all the entries. And obviously we can say here, out dot print LN. So let's say department. Okay, department. And obviously we want to, in the entry dot get k, you will have actually the Department, because that's the key. And then we need to just look through the values, right? So it's like employee E and entry dot get value to it, just looping through the list of employees. And here we can obviously do a System.out.println. So let me just copy this line. And we want to now print all the employees. Okay? Right, so what we have done is we have just, we're just looping through that map now and printing it right? So obviously we have to now call this method here. So let's just call this method in our main method. And let's pass the employees, right, so we're done, I think in the old style, let me just try to run this program to see if everything is working fine. And as we can see, the it is actually printing the employees by itself, right? So the finance department, we have two employees, Martin department, we have two employees, digital, we have three employees and sales, we have four employees, right? So pretty good stuff. Okay. And this is a use case you'll see in pretty much in all projects that you'd walk on, right? This kind of use cases. So okay, so this is how we do it in the old style. Now what I'll show you is how you can implement the same use case in the new functional style. So let's just Coffee business method. Obviously, I'll get rid of almost everything from here. Okay, and I'll rename that, let's say to something called employee or department in functional style, let's call it as a muscle that we know that this is the functional style, right? Okay, so same thing, we have a new method now. And here we are going to implement the same use case in the functional style. We are passing a list of employees and we have a new empty HashMap. Okay, so let's just look through the employees so we can say Employees dot forEach, okay? And as we can see the forEach, except a consumer, we know how to implement consumer. Now, consumer is like supplying one input and not returning anything, right? So what we're passing is the employee object. And for this employee object, what we can now do is we can say, let's try to get the department. So employee dot get the department. Okay? And then we have now a very interesting method. Okay, So if you just do employ our departments on this map, we have something called compute if absent, okay, So if you see the parameters for this, we have to pass in a key and the function, a mapping function, basically, right? So what we need to just pass in here is the key or key is nothing but the department. And we need to pass in a function. And the function that we will be passing in is let's say department, we can say d, you have to return new ArrayList. So we now have the list of employee. And to this now we can do a ADH of employee. Okay? Yes, see on the map interface we have this method compute if absent. And in this we pass in the key and a function, okay? So the key is nothing but here the department and we're passing a new function wherein we are just supplying the key and adding a new ArrayList. What this will return is, it returns basically a list of employee here, as you can see. And to that now we're actually adding the employee. So this is how you can take the advantage of functional programming because all we're doing is we're just passing in a function and then adding the employees. Okay? So this is a true use case of functional programming that we have seen, right? I hope this is clear now. So next what we'll see is we will be now printing this map actually. Basically we'll be implementing this part now in a functional style. Okay? So this is again a very common use case. And this use case is all about how do I print everything inside the map in the functional style. So for this, what we will do is we will call the map. And on the map as well, you have for each and the fourier edge, you can see that it accepts a bike consumer and on the list if excepts the consumer. So we need to implement a bike consumer, right? So to the bike consumer, what do we need to actually pass in is obviously two variables we need to pass in. Let's call those as, let's say department. And I will not say employees. Let's say I'll call this as a employee list because this is actually an employee list hour. So we're just passing the key and the value is ugly here. And now to this, by consumer again, doesn't return anything, it turns white. So here now we can actually implement our logic. So here I can call in this, let me just copy paste this because this is the same. Obviously here, I already have access to the key which is nothing but the department variable. And next is I have access to the list, right? So I can now say employee list dot forEach. And again here is we have to pass in a consumer. So basically we're just looping through the, the map. For each map we are passing in basically passing invisibly the department and the employer list and we're looking through it and we're just printing everything that's present inside the map. Now, if I just call this in our main method, same thing. If we just pass in employees. Obviously, I'll just comment out the previous one to show you that it is working fine. So I'll just maybe run this now. And you can see that it is exactly printing the same output, right? This use case is something which is very important and you will be finding it in all your project that you'll be working on. So I would say just implement this use case by yourself so that you can understand how this kind of use cases can be implemented in the new functional style. Okay, in this video, we saw the functional interfaces function consumer and by consumer For the, for each we passed into by consumers in this, the first time we saw by consumers. So understand how Bitcoin works. And next we also saw a function. So here in the computer, if absent, we actually need a function. That's what we're passing in. This is the function we're passing in. And at the same time we saw for the 48, we're actually passing in a consumer which we have seen many times now in this course, right? So that's all in this video. I hope you found this video very useful, but thanks for watching and see you in the next video. 16. Functional Composition: Hey guys, welcome back. Okay, so now that you understand the basics of standard functional interfaces and in the examples we have worked with, you have experienced the essence of functional programming and which is a programming style in which you pass a piece of code as arguments to methods in the same way as you pass values as arguments to methods. Now in Java, all this is possible due to this functional interfaces, lambda expressions and method references that we have seen in the previous videos. But there's more you can do with the standard function interfaces. And thanks to functional composition, and that's what we'll see in this video. We will talk in depth and understand what is functional composition. So functional composition to the technique, combine multiple functions into a single function. So here we just combine to function, right, into a single function. That's what function composition is all about. In mathematics, you might have already come across this concept of functional composition. So in mathematics, the functional composition is the application of one function, the result of another to produce a third function. So for instance, the function, let's say if that takes input as T and gives the output is r, Then we have another function whose input is R and the output is u. And then when you do a composition of those two functions, it can be composed to yield a third function, which is hitch, and we call it as g of f of x, right? Which maps from v to u. So the input is your T and you'll get the output as you write. And that is what is actually functional composition where we combine multiple functions into a single function. Now if you look at the API documentation of the interface and the package Java.util or function, right? There are methods such as and then, and then compose in those functional interfaces allow us to perform this functional composition in Java. Now this is all theory and it might be a bit confusing to understand. I think the best way to understand functional composition is through examples. So let's jump onto the intelligent code and try to implement some functional competition. Okay, so what I've done is I've just clone the example 0 six year into 0. With the help of this example, I just tried to explain you the concept of functional composition. We have seen this example before. If I just try to run this example, it just prints the salary, right? So what I can do here is I can say another map here. And I can then. So let's say whatever salary I have received, I can just format that salary actually here. I don't know how we can do that is I can say, you know, let's say whatever I just received. So I can say salary. And I can just format that to a string dot format. Okay, So let's call this a name. Let's use this employee name here as well, right? So what I'm trying to do is this employee that I've found. I mean, I'm just getting the salary of the employee and then I'm just formatting the salary. So that's what I'm just doing in this line, single line that you see here. If I just run this now, we'll see that the salary is now formatted, say the salary of stimulus, so and so dollar. So what we're doing here is we're doing to mapping with the help of two functions, just to make it clear what is happening, let me just now split this into two functions. So I will just split this first into, it's actually a function of employee. So if the input is employee and the output is BigDecimal, right? And here what L passes the employee as the input. And what the output would be is employee dot get salary. Employee dot get salary. So this is the output we have. Now, obviously I can very well then replace this part of the code that you see here with this function that is employed to salary. And let me now write another function. Let me just copy paste this line. And now this function is basically taking the input as the big decimal is just take an input as a big decimal and the output is a formatted string. Okay, so let's say, let's call this as employed to salary formatted string, right? So, okay, so it's basically this method that we have here, okay? So I can just put this method to displace, right? And then I can just copy this method here. Okay? So now the same thing, I've just split into two functions just to make it very clear to you guys, right? So here all I'm doing is employee dot map. And in that I'm passing the first function that is employed to celery and then again mapping it, this time from employee salary to a formatted string and you present, I'm just printing it. Now. We have two functions, right? So what we can do now is instead of doing it in two stuff, so I can write a third function. Now let's, and this function, we can say it's employee and the formatted string is the salary. Okay? So let's call this as, it's called this as composed, a composed function basically. So we can say now, here, we can say employee's salary, right? And we can say, and then, okay, and then the formatted string, okay? So we have this compose functions. You're actually doing a functional composition of two functions. What are the two functions? The first function and this is second function. And then we don't need to now do it in two steps. Instead, what I can do is just copy this and maybe then comment it out. So instead of doing it now in two steps, I can now do it in a single step. I can just pass in this function. And this is what is functional composition all about, right? So we have two function that we are combining into one function with the help of this and then method. Okay, So this is what is helping you to form this functional competition. Now, another way you can do this same thing is with the help of the compose operation. And the whole operation works in the reverse way. So the compose operation unit to first call the second function, and then you have to say compose, and then you have to actually invoke the first function. And this is exactly the, it gives you the same output. It just that when you use the composer doing the reverse prefer just run this code now, okay, you can see that the same salary is printed. So this is what is functional composition all about. That is combining two functions into one function. Now there's one more example I just want to show you just to make the functional composition concept very clear so that you know the use cases of functional composition. So for that, I'll just create one more example class. Let's call it 09, and let's just clear everything up, right? And then what we'll do here is, I just want to show you how you can do pretty good composition. That's like you can actually supply two predicates and combine that into one predicate. Okay, that's what we'll see in this video. So this is the simple example that we saw in the previous video. We'll actually find the implied with Hyper-V predicate, right? Let's say for some reason we have now two conditions. So what I've done is I've just created two predicates you write. And my two particular sir. One is that the department is is finances the where the employee belongs to the finance department. And essentially I have the criteria that the cell should be less than this range. Okay? So this is what I have just quickly created to predicate. Now, the same method that we see here where we're actually passing one predicate can be re-used now with the help of functional composition. So here what I'll do is optional employee, employee musical to find employee. And in that, obviously I'm passing the employee list. And now we'll, I'll do a functional composition of my predicate. So I'll do is finance and, and his salary. Okay? So with the help of this and method, I have assumed a functional composition of two pedicles into one predicate. And then what I'll try to do is I just tried to print the employee. So if I just run this program now and we can see that the employee is printed and he is indeed from the finance department. And this is how you can actually achieve functional decomposition. Getting this example actually we have combined to Predicate, combined and made into a one predicate. And with the help of this kind of concepts which you can build your search patterns based on different criteria. So that's all for this video. Thanks for watching and see you in the next video. 17. Primitive Types - Specialized Functional Interfaces: Hey guys, welcome back. In this video we'll see some specialized functional interfaces. Functional interfaces that deals with the primitive types. Well, you now know almost everything there is to know about the standard functional interfaces. But if you have looked at the API documentation of the package Java.util or function. You might have noticed that there are more interfaces than the ones we have been working with so far, right? So in this video we'll talk about those specialized functional interfaces, mainly that deals with the primitive types. All of the extra interfaces that we haven't looked at so far are specialized version of the ones we have been working with. What I mean by specialized is that they have been designed to work with specific primitive types rather than generic types. As you might already know as a Java programmer that Java has primitive types and reference types. Right? Now, primitive types are simple and efficient. Variable of primitive type directly contains a value. If a variable is not a primitive type, it's a reference to an object is stored in memory. So compared to the primitive types, the reference types are less efficient in some ways because to get the value that's stored in the object, the reference will have to be dereferenced, which means that object has to be looked up in the memory first, which is an extra step that the Java virtual machine has to perform before it has the value at hand for processing this, right? So this is why the reference type is less efficient than the primitive types. Okay? Now also as you might be aware that in Java programming the generics only work with reference types. You cannot, for example, heavenly stop primitive int values in Java, right? Because this is not possible in Java, that list of primitive type int is not possible in Java. So if you need to store values in a list, you will have to wrap each value in java.lang dot integer, right? And this is inefficient compared to working with primitive types. Now, many of the standard functional interfaces we have worked so far have type parameters to allow them to be used with arbitrary types. Now to understand this concept in depth, let's look at a simple example. So what I've done is in this example, I've just written a method named calculate integer that accepts two integers a and b. Then we have a binary operation function that performs the operation on this two integers, a and b. And from then from the main method I'm just calling the calculate integer method and passing two integers and passing the function here. In this case, we're actually multiplying it right? So if I just run this, the output is 1200. And if I just do, let's say a plus B, the sum would be 70, right? So it's a very simple function. But why I wanted to show you this is that in this style, it is actually we are using the wrapper integer object, but not the primitive integer. But here, when you're passing the inputs to this function, we're actually passing in the two primitive types, right? 30 and 40, which is actually kind of box into integer objects, which would be passively lambda expression and where they would be immediately unwelcome again to perform the calculation. And then the result would be boxed into an integer object and, and then unbox it again into an int primitive value. So in short, what we can see is that we have three temporary integer objects that has to be located initialized and deallocated, which is inefficient and unnecessary, right? And exactly to handle this situation, this problem, we have a specialized set of functional interfaces that allows you to perform this functional programming on the primitive types, right? What we can do instead is we can actually write another method here. And let's call it now. Let's say, instead of saying calculate integer, let's call it calculate. And this time let's pass the primitive types int a and b. And let's use this term. Very specialized functional interface for this, we have int binary operator. And what the int binary operator does is it will actually we have a function named apply as int, right? So there's no need of any wrapper object because what this is capable of handling the primitive integer type. So now what we can very well do. We can say here, instead of saying calculate integer, we can just invoke the calculate method. Okay? If I just tried to execute this, obviously both will give you the same output, but this one is more efficient. Why? Because there is no need of boxing and unboxing of the wrapper object, right? So that is why this is more efficient way of programming, and that is exactly why we have this specialized functional interfaces defined. Now the question you might have is, so do we have specialized functional interfaces defined for all the primitive types? So the answer is no, we only have specialized primitive types for the int long and double. We don't have specialized primitive types for all the eight primitive types that we have in Java, right? So it's only for the int, Will and long. And these are the list of all the different specialized functional interfaces that we have for the primitive types. So whenever you are dealing with primitive types, use this functional interface is instead of using the generic functional interfaces that you saw in the previous slides, right? So just go through this list and you know, and understand in depth what this specialized functional interfaces are. Therefore, main thing that you need to take away from this video is that use specialized functional interfaces when you're dealing with primitive types instead of using the generic functional interfaces. So that's all in this video. Thanks for watching and see you in the next video.