alright so we created the predicates to call the print employees by age method in
the last video lets just run this to see that it does actually work and you can
see we have successfully got to both methods working now both the employees
over 30 and also the ones 13-under so as you can see the predicate arguments are
just lambda expressions that match the predicate interface the accept one parameter
and return a boolean value and I would hope that this point you think that this is
actually quite powerful because we can pass all sorts of conditions to the
method and we don't have to write a different if condition to filter the
employees based on different age criteria all we need a new lambda expression
that can map to the predicate interface now I mentioned in a previous video in
this section that we don't have to use lambda expressions we can always use an
anonymous class and that's also true in this case we can pass an anonymous
predicate to the method let's do it that way to print all employees that are younger
than 25 let's add this code to the main method below the other calls that
we've added to the print employees by age method so do....
....
.....and I've got the option by
IntelliJ so if I press enter it will create the anonymous class for us
like so and notice how it's already overridden the boolean test so we all need
to do there is return an expression and expression obviously need to return
true for whatever condition we want to so in this case we're going to return
employee.....
....and if we run this
you can see employees younger than 25 tim buchalka 21 he wishes and
also Snow White who was 22
so that's obviously working as well so yes we can use an anonymous class here
but when working with interfaces in the java.util.function package it is
more common and I think personally more convenient to use lambdas but if you're
reading code that someone else's written then that's what you see but if you
really don't want to use lambdas it is possible to do everything by using
anonymous classes like I've shown you there now the consumer and
predicate interfaces are general interfaces don't care about the type of
parameter being passed to the lambda expression using generic to infer the
type now there are other consumer and predicate interfaces that expect a
specific type of parameter for example the double consumer expects a lambda
expression that has a double argument now there's also an int consumer and
a long consumer in addition to predicate there's also double predicate
int predicate and long predicate where possible you probably should use the
more specific type of lambda to improve readability so it just in line with that
let's add an int predicate to the main method that actually tests whether an
integer is greater than 15 so we can do that by typing....
....so right now the int predicate
doesn't do anything just like an anonymous class instance that we
assigned to a variable we have to actually use somewhere so let's print out
the value of the predicate for the value 10 now remember that we have to call the
method that the lambda maps to which is test in this case the value we are going to
pass is 10 so let's just try that....
....
...if we run it
because of course 10 isn't greater than 15 you can see we get false printed to the console
and we can pass any integer value to test including a mathematical expression
that returns and int an int variable or method that returns and int so let's use
the result of say variable and adding some number to it just confirm this
actually works the way we think it does down here will put something like....
....
.....you can see true is printed out
to the console so this shows us that we can reuse predicates in this way and now
another cool thing about predicates is that we can chain them together for
example let's just say we wanted to test whether a number is greater than 15 and
less than a 100 now we could update our existing predicate to include the
second part of the condition
let's just say we don't want to do that because we want to use our existing
predicate perhaps elsewhere what we do in that scenario is create a second
predicate and chain it to the first one so first we'll change the name of
it into something more descriptive and let's use some refactoring to rename
that so going to right click here and do a refactor rename and we'll
call something more descriptive let's just call it greater than 50....
....
press ENTER now lets then create a second int predicate and that's
going to test whether an integers less than a hundred i'm going to type....
...
....and we will print out the results
....
...let run that and you can see we've got a true in that last scenario and the 3 is that the
number 50 is greater than 15 but less than 100 and incidentally the test
method will return true if both predicates return true when evaluated and false if
one other predicates returns false if we do that again in another scenario lets
just add another line there where we know we want it to fail so say 15 is going to cause
obviously greater than 50 to be false but the less than a hundred will still
be true we run that we should get a false because one of the predicates is now
false you can see on the bottom we've got false showing now you'll notice that
both our predicates use i as the parameter now remember that each lambda
expression is like a nested block so imagine each line of code surrounded by
curly braces so again the the actual scoping that's working in this scenario
for lambda expressions is something like this
....
.....
so that's essentially what's happening here in other words each variable is within
the scope of a single lambda and that's why it's ok to use the same name here
now whether that's good for code readability of course is a different question now
the predicate interface also contains or negate and is equals methods the
more specific predicate interfaces contain or and negate but they don't
contain is equals and they don't extend predicate the and/or and negate methods
can be chained together this chaining is useful if there's a
situation where we need to build a condition on the fly or when we want to
reuse some predicates in different areas of application
so next we're going to take a look at the supplier interface now a supplier
doesn't accept any arguments and it does return a value
let's look at an example lets just assume that we want to print out 10
random numbers so I'm going to just delete this scoping code that i added
alright so going to delete that code lets just come up with a
scenario where we want to print 10 random numbers the first draft we could
do something like....
....
and if you run that we should see 10 integers showing there you go 10
integers showing on the screen and obviously if we wanted a smaller subset of
numbers we could put pass a parameter to say to use the range 0 to 99 and
run that again and we only get numbers within that range that's working
let's change the code to use a supplier instead now because the supplier
always returns a value we have to include the expected return type when we
declare it
we're going to use the get method to get an object from the supplier so the
revised code would be the first line will be the same but the line after the
random we are going to put supplier the type is going to be integer....
....
.....
....
so if we run that you should find that we still get 10 integers just like
we did with the previous code and there our 10 integers now notice the empty argument
list here that doesn't look at all interesting and just as with other
lambda expressions we can pass suppliers to methods so you could have a situation
where sometimes you want to supply an object of type a and other times an
object of type b where b is a subclass of a or perhaps we may have a case
for a supplier is providing an i/o stream was used as a counter so we
can also use suppliers when testing an application a supplier could instantiate
objects and perhaps populate them with random values so just as with predicates
there's more specific flavors of suppliers as a boolean supplier a double
supplier int supplier as well as a long supplier i'm going to finish the video
here now in the next video we're going to continue on and we're going to start
looking at a function lambda which uses the function interface to call
lambdas is in a different way
let's work on that in the next video