Sunday, December 9, 2018

MORE USAGE OF LAMBDA EXPRESSION AND Funtional Interfaces.

You can use comparator directly in a list for comparing objects. For e.g you have a list of Person and you want to sort it on the last name all you have to do is :

Collections.sort(personList,(p1,p2)->p1.getLastName().comparteTo(p2.getLastName));

or Similarly,

personList.sort((p1,p2)->p1.getLastName().comparteTo(p2.getLastName));

Another example, you want to have a condition that goes through all the person object. For e.g what is you want to print all persons with the last name beginning with a particular letter such as "C" or "D" or in short you want to add a condition that takes an object and test something on it and returns a boolean.

lets implement this requirement first so it will be easy to follow:


public static void printLastNameOnCondition(List<Person> people) { 

for(Person p : people) {
    if(p.getLastName().startsWith("C")){
    System.out.println(p.toString());
}

if(p.getAge()==30){
    System.out.println(p.toString());
}
}
}

Obviously, this looks strange you have to add more "if" blocks in order to insert another condition. What if we create an interface of Condition and provide an abstract method of test and the implementation will be a lambda expression. Like this:

@FunctionalInterface
public interface Condition{
public boolean test(Person p);
}

public static void printLastNameOnCondition(List<Person> people, Condition condition) { 
for(Person p : people) {
if(condition.test(p)) {
    System.out.println(p.toString());
}
}
}

public static void main(String args[]) {
    List<Person> people = getThePersonListFromSomeWhere();
    printLastNameOnCondtion(people, p->p.getLastName().startsWith("C"));
    printLastNameOnCondtion(people, p->p.getAge()==30);
    printLastNameOnCondtion(people, p->true);//print all person objects
}

These type of common patterns of test on condition has also been entertained as funtional interfaces in java.util.function as Predicate. That means you can use the already defined Predicate interface instead of specifying your Condition one. The Predicate has one abstract method with name test. Therefore, using the Predicate will remove the Condition interface and the code becomes like this:

public static void printLastNameOnCondition(List<Person> people, Predicate<Person> condition) { 

for(Person p : people) {
if(condition.test(p)) {
    System.out.println(p.toString());
}
}
}

public static void main(String args[]) {
    List<Person> people = getThePersonListFromSomeWhere();
    printLastNameOnCondtion(people, p->p.getLastName().startsWith("C"));
    printLastNameOnCondtion(people, p->p.getAge()==30);
    printLastNameOnCondtion(people, p->true);//print all person objects
}

The package has lot of predefined interfaces that can be used in such common scenarios, you need to practice them in order to remember.


Some other concepts around lambda:

When you are using any variable that has been defined in the body of the function which holds the lambda expression and if you try to change the value of the variable it will show a compile time error that the variable must be declared final or it should be effectively final. It means that the JVM will use the value of that variable in lambda expression that can be use at later point of time and the value must be freeze at the first initialization. 

Effectively final means you do not have to put intentionally the word final before the variable but if you would not change the variable value again it will be considered as final since the first value has been frozen. 





Let me explain the concept of Closure with the help of example:


public static void main(String args[]) {
   int a = 10;
   int b = 20;
  
   doProcess(a, i -> System.out.println(i+b));
}


public static void doProcess(int i, Process p) {
    p.process(i);
}

public interface Process{
   void process(int i);
}


At the lambda expression, this expression will pass as the body of the implementation of Process and it is pass to the method doProcess, here, the method will accept it and execute it from the body, notice 'b', it is coming from closure, (closure means an act or process of closing something), when there is variable in a scope same as the lambda expression and it is being use (as in here) in lambda expression the JVM will close the changing ability of variable 'b' since the lambda will be pass and can be use at the later point of time till then it is necessary for that variable NOT TO Change its actual value. JVM does that for you and close it for further changes (you can try by assigning another value to 'b').

The This reference:


As you know we cannot access 'this' reference in static syntax, this reference to the object and static is something that is related with class.  The this reference is different in terms of lambda as compared to anonymous classes as I have mentioned before lambda expression are not anonymous classes here is one of the proof. when you will try to use the this reference in a class.


When we create an anonymous inner class and use 'this' it will reference to the anonymous inner class not the Parent class. However, if 'this' reference is use in the lambda expression it will point to the object whoever the other code outside the lambda is pointing to. That is, the lambda expression share the same reference with the code in which the lambda expression has been written. As compared to anonymous class it refers to the anonymous class.









References: javabrains.io


Why Functional Programming?

The answer to this question lies in the essence of the usage of functional programming, the basic or foremost advantage of Functional programming is that it promotes pure functions, a functional approach involves composing the problem as a set of functions to be executed, functions that are self contained and free of side effects, which result is dependent on the passing arguments i.e stateless.
With these two attributes (self-contained and stateless) of function programming, it opens a number of benefits such as :

Increased readability and maintainability. This can only be achieved if the programmer has an understanding of the relative syntax and the specific task. Becuase, each function is designed to accomplish a specific task given its arguments. The function does not rely on the external state and that also makes it easy to refactor.
Easy testing and debugging. Due to the fact that pure functions can be easily tested due to their limited scope, you can write test code that calls the pure functions with typical values.
However, a lot of things are hard to understand with the FP point of view that is why the usage of functional programming is like a syntactic sugar on stuff good programmers have been doing for years. To my understanding, it has been added for some scenarios, its like another tool in your tool box to make an efficient solution to a problem.

Why Lambdas? (Get back to this after tutorial)

It enables functional programming in java. It is elegant in certain scenarios, In object oriented programming all your logic is related to some class or some object. If you have to pass any behavior to a method then you have to create a type that will have the definition of all the behaviors and the instance of that type will be passed into the method argument. For e.g. we have a greet method that need to print greeting according to the situation, one thing we can do is write every possible greeting that can be passed as an argument and write a switch block to handle that request. However, it is not an elegant design what more we can do (in JAVA 7) we can create an interface and abstract all the possible greetings over there and pass an implementation of the type and greets accordingly.

public void greet(GreetInterface greetImpl){
greetImpl.greet();
}

still we are not passing a behavior but we are passing a thing that has a behavior, what if we just pass the action it self to the argument which does not belong to any class and it can be pass as an argument..?
Lambda expression enables you to do this they enable you to pass your function implementation directly in your code.



References: javabrains.io

Functional Interface and Lambda Expression

For example, writing lambda expressions for

doubleNumberFunction = public int (int x, int y){
if(y==0) return 0;
return x*y;
}

What about the type of the variable of doubleNumberFunction?? there is no Funciton type but they have a concept of Functional Interface. Now, let's leave the above function and pick up the scenario that has been discussed in the starting of this blog.

We were trying to pass a behavior in a greet method and elegant way to do was to pass the implementation of an interface that holds the particular greeting. For e.g. we have different greetings: Birthdays, Wedding Annivesaries, Brand Annivesaries e.t.c. Let's say, all of them will have a greet message for now and will respond particular message that means, all of the implementation classes will have one method implementation and the type interface will have one abstract method.

interface Greet{
public void greet();
}
public class Birthday implements Greet{
public void greet(){
System.out.println("Happy Birthday");
}
}

and so on with the other implementations. Here comes the Functional Interface into the picture, in java 8 Functional interface has been introduced, which is simply define as an interface which have only one abstract method. As in java 8 we can have default methods as to give default implementations but to be a functional interface it should have one abstact method it can have any number of defauilt methods but one abstract method.

The type of a lambda expression holder needs to be of Functional interface. To make an interface Functional we just need to add an annotation @FunctionalInterface like this:

@FunctionalInterface
interface Greet{
public void greet();
}

Now we can have the implementations/function write as lambda expression and directly pass into the Functional interface type holder.

Greet lambdaGreet = () -> System.out.println("Happy Birthday");

This looks similar to anonymous inner class but it is different, lambdas and anonymous inner classes are different things.



References: javabrains.io

Type Inference and the Reason For Functional Interface

The word inference means a conclusion that has been reach on the basis of evidence and reasoning. Here, the type is the evidence that can be use to reach a conclusion of lambda expression. For e.g. in our class where different greetings need to be implemented and we have define one interface Greet for it. Let's add a parameter into it for more understanding.

@FunctionalInterface
interface Greet{
public void greetMessage(String name);
}

when we are using Greet type object to pass around the method as a lambda expression holder and particular name for print with that message:

public GreetRunner{

public static void printGreet(String name, Greet greet){
greet.greetMessage(name);
}

public static void main(String args[]){
Greet lambdaGreet = (String name) -> System.out.println("Happy Birthday"+name);
printGreet("Fahad",lambdaGreet);
  }
}

Greet lambdaGreet = (String name) -> System.out.println("Happy Birthday"+name);

Here we can use directly the lambda expression, instead of just passing the variable we can pass the lambda expression. Furthermore, we can omit the type String from the parameter since the Type of the lambda or the functional interface method has defined that it is a String Or in other words the interface is infering the lambda expression by providing all the reasoning and evidences from the interface method definition.

printGreet("Fahad",(name) -> System.out.println("Happy Birthday"+name));

One more thing is that, we can actually remove the round brackets if there is only one parameter. Therefore, the last simplified version would be look like this:

printGreet("Fahad",name -> System.out.println("Happy Birthday"+name));



A Reason for Functional Interfaces


Why they have not created new Function type or Lambda Type the reason is to make it flexible in terms of compatibility. If they have created a Lambda type then all the lambda expression will be valid for that particular type only. In case of new function type you have to write another lambda type and change the implementation. 

Advantage of using interface is that you can use lambdas in the place of all the anonymous inner classes and methods which accepts the interface you do not have to rewrite for a new function type. For e.g in Runnable there is one method "run" in jave 8 it has been declared as Functional interface. We can use the lambda expression instead of write the anonymous inner class to make the object of thread.

As for java 8 we can add implementation to the interfaces as default methods. To be use an interface for lambda expression that interface needs to have only one abstract method, it can have multiple default methods but one abstract method. Though the Java compiler will not complain if you do not define @FunctionalInterface annotation at the interface definition but it is a good practice to put on it, therefore, other programmers know the purpose of the interface. However, if you add another abstract method while the annotation is there it will show compile time error.





References: javabrains.io

Lambda Syntax

Let's make it more sensible and understand the lambda expression, let's discuss the syntax first by starting from the initials:

lambdaHolderVariable = public void greet(){
System.out.println("Happy Birthday");
}

since the piece code will be use in a block there is no need to define as public/private/protected it will be scoped in a place between you lines of code whoever using the variable will have the acess of the method so we can omit the modifier.

lambdaHolderVariable = void greet(){
System.out.println("Happy Birthday");
}

Now the java 8 compiler is smart enough to look at the method body and tell what is actually the method is returning, likewise we know the body is returning any thing it is void, if it is returning any thing it will also be recognise by the compile. Therfore, the return type goes away.

lambdaHolderVariable = greet(){
System.out.println("Happy Birthday");
}

Now, as you can see we already have a variable that holds the name of the logic that contains inside the braces, therefore there is no need to define multiple names of a block of code, so let's change it and the color again.

lambdaHolderVariable = (){
System.out.println("Happy Birthday");
}

What has been added here in Java 8 is an expression that helps developers to easily recognise a lambda expression i.e. "->" and it is placed between empty brackets and starting curely brace. 

lambdaHolderVariable = () -> {
System.out.println("Happy Birthday");
}

Moreover, if there is only one line in your method body, you can actually omit the curely braces, but if you have more than one line you have to provide the braces. 

lambdaHolderVariable = () -> System.out.println("Happy Birthday");

That's your lambda expression.




References: javabrains.io