refermycode.com

Develop your world..

Lambda Expression with Example

Hi Techies,

In previous blog, we have learned basic introduction of Lambda Expression. Now, we are going to learn few examples and some new APIs using Lambda Expression in detail. so before proceeding further, lets brush up some basic concepts of Lambda Expressions in something different way.

What is Lambda?

  • A Lambda is a function.
  • A function is computation that takes parameters and return value.
  • Until Java 8 function could be implemented by using methods.
  • A Lambda enables function to be passed around or stored like data.

Let us consider following example of sorting the list of Person objects with the name of person.

This is basic syntax to sort a list of object.

So in above example collections.sort() method requires parameter of type comparator, so we need to wrap compare method to one class which should need to implements comparator interface. But still we cannot call comparator class because sort method needs instance of comparator interface. so we are creating instance of comparePersonByName() class and passed to the sort method. So basically we are passing instance of comparator to the sort method.

This is sometimes becomes a problem because, The class that defines comparator sometime is far away from where it used. If our application have multiple files then it is difficult to figure out where actually comparator is located in our file system.

In order to deal with this problem, We can inline the compare() method inside an anonymous inner class. This avoids problem of declaring class into the somewhere else.

But there is lot of complexity here, both in the syntax and in fact we are creating a class and creating an instance of it, and just passing that instance to a function to sort method.

So let’s remove some syntax from this Collection.sort() method to simplify the structure of the code.

So now our syntax contains a method body which takes a 2 parameters Person p1 and Person p2 and perform some operation on it with compareTo() method and returning value to the Collection.sort() method.

So we can rewrite this into our first Lambda Expression, it just a function like,

So parameter are passed on the left side of an expression and list of parameters are enclosed with the parenthesis. The body of lambda expression are defined on the right side of special symbol -> (Arrow syntax) which is basically used to declare a Lambda Expression.

We can reduce the code Syntax as further,

Since we are sorting a list of Persons, the comparator function must be comparison of 2 Persons. The compiler knows this and hence it uses Type Inference to determine the types of parameters.We left off the type decoration making the Lambda Expression even more concise.

Note that, Java is still statically tie, means the type of p1 and p2 are still Person. They are determined at compile time. If compiler does not have information to infer what the type of p1 and p2 then it will generate the compile time error.

The sort method still calling compare() method, Even if we have not declared any compare method in the syntax of above mentioned Lambda expressions then How would you know that it is compare method?

Here is the answer,

Comparator is a special kind of interface called as functional interface. If you are declare a class which implements an interface then you need to provide implementation of each method declared in it. A Functional interface is an interface where you only have to implement a single method. In case of comparator it is the method called compare(). But since there is only a single method that you need to implement when you provide a Lambda Expression for it you don’t have need to provide the name, the Lambda Expression implicitly implements that single method inside the functional interface.

The all syntax which is used in the Lambda Expression we are already studies in the previous blog. If you want to know about the all syntax then please go through the previous blog.

Now we are going to learn why Functional Interfaces are important?

Anywhere functional interface is taken as argument you can write a Lambda Expression for it. Lets check out some other functional interfaces that already existed in Java 7, even though they wouldn’t called as functional interfaces previously.

A common example Is the Runnable interface. It defines a single method called run(). To create a new thread, you need to pass instance of Runnable interface to the Thread constructor. The tread will invoke the run method of Runnable interface. So below example will show how to create a thread using anonymous inner class.

so we can use the following Lambda Expression to perform the same operation which is mentioned in above example.

So in many cases the expression declared in anonymous inner class is replaced with Lambda expression.

New APIs using Functional Interfaces:

Oracle have added several new APIs in Java 8 that takes an functional interface and hence we can use Lambdas in it. For example let us consider the task to printing out each person in a list of Person.

Example 1:

We can use new forEach() loop to print out the list of Person with the help of Lambdas.

It might not seems very significant it look like we have just rearrange the syntax but this is an example of Internal iteration vs External iteration.

Lets us modify this list into the synchronized version of list, so that following example will make difference between Internal iteration and external iteration more clear.

so now this version list is a synchronised list which can be operated by multiple threads simultaneously.

The for loop which in body External iteration is implemented by using iterator. The for loop repetitively call the hasNext() and next() method of iterator (i.e. Two methods are concurrently working on the list). Since the list is synchronised list each method call on the iterator is synchronized, however another thread can modify the list between these calls if this occurs next method call on iterator results in concurrentModificationException. This example shows that the loop is been control from outside of list hence it is External iteration.

The forEach method on list illustrates Internal iteration. This is single method called on a list so list is synchronized for the entire duration of call and in such condition concurrent modification is not possible. Iteration of whole list Happens inside the single call hence it is Internal iteration.

Example 2:

Here is the another example in which we have to remove the all persons from list which having name equals to “ABC”. So we can find all such a type of person by using conventional for loop, but we can’t do the actual removal of that object. The reason is that we can only remove element by using remove() method of iterator but in for loop we do not have access to iterator that the for loop is using.

Instead of that, we need to write the for loop into long form, i.e. we have to explicitly get the iterator in advance using hasNext() and next() methods. Then we can call remove() method in appropriate place when we found person which match the criteria inside the loop.

In java 8, we can handle this situation by using new method removeIf() which removes each element from list where Lambda Expression returns the value as true.

Example 3:

Here is another example with new method which is used with Lambdas. Suppose we have to replace each element of list with uppercase equivalent. We can use same for loop which is use in the previous example with listIterator. Within the iterator we can use the set method listIterator to replace the new values with its uppercase in the same location.

So we can perform same operation with the help of Lambda Expression by using replaceAll() method.

Default Methods :

In Java 8, oracle has added new feature called as Default Methods, Default Methods has an implementation inside the interface, so for any class that has not provided implementation of this methods, the default implementation is used instead of that.

Default Methods are just like virtual methods, they can be overridden by subclasses. So following are the default methods which are added into the respective interface.

The list.sort() is replacement of Collection.sort() method,
Here is example of list.sort() method,

Above syntax can be replaced with,

Higher Order Functions :

Lets consider the following example which is used to sort the list with the help of comparator. In many cases same structure is used to sort the list with following manner,

Wouldn’t be nice if we can replicate that structure more easily?
So oracle introduce new method called Comparator.comparing(). this is higher order function, which is function that consumes or returns other functions.

In this case, comparing function takes function and gets right data from person object, this getter is called on each of the two Person objects and calls compareTo() on that values. The comparing function doesn’t do the comparison itself instead it construct the comparator function and returns it and this return is passed to list.sort() method.

Method References :

We have seen few lambda expression which are in the form of given an object, called method on that object and return the result. This form of lambda are so common, oracle has created a shorthand for it called as Method References. Using the new :: operator, we can mention a method by classname and methodname and it is equivalent to writing a Lambda Expression that takes an object if that type and calls the method on it.
Here we are rewritten the previous examples by using method references,

Two Level Sorting :

Let’s move to more complicated example of 2 level sorting. Suppose we want to sort the list with the age of Person and within the same group of age we have to sort the list by the name. So below is the code to sort the list using anonymous class,

In this example first compareTo() method is returning the result of ages while second compareTo() method is returning the result of comparing the names.

So it’s looking very complicated but if we break it down then we observe that it is combining the result of two comparators. Means if result is unequal then we are done and if result is equal then we call the second comparator and return its result.

We can use higher order functions to take two comparators and combine them into one.

So here the higher order function because it takes one function as parameter and returns value if that function to another function,

So firstly, we are sorting the list with the age with the help of first comparator which is invoked by comparing() method, if result of this comparator is equal then the result of this function is passing to another comparator which is sorting the list with the name with the help of new method thenComparing().

We can make this code more concise with static import,

So code readability is also increased by using the Lambda Expressions.

Old vs New :

Here is same code with the Lambda Expression,

here is the old and new code, side by side, Not only does old code have lot of inner class where embed it also embed some logic that isn’t very obvious. If you reading this code for first time then it can be hard to understand. By contrast the lambda based code makes it easy to create a very complicated structure by composition of small parts. Its pretty easy to create comparator using comparing() function. Its also pretty easy to combine comparator using the thenComparing() method. The resulting code is clear,concise and easy to modify.

Summary :

  • Lambdas are functions.
    A lambda can often replace an anonymous inner class.
  •  Java SE 8 defines new APIs using functional interfaces.
    Java 8 defines several new functional interfaces and new APIs that use them enabling them to be used with Lambdas.
  • Default Methods
    Default methods enable interfaces to view add compatibility.
  • Method References
    Method references are used for short hand Lambdas.
  • Higher Order Functions
    Higher Order Functions enables creation of more complex functions by composition of simple functions.

Lambdas make code read more like the problem statement. The resulting code is clear, concise and easy to maintain and modify.

Hope this blog will help you to understand some new APIs using Lambda Expression with Example in Java 8.
Please don’t forget to comment your feedback for this post. 🙂

References : Video of Stuart Marks – Oracle Corporation.
Image Courtesy : http://blog.takipi.com/compiling-lambda-expressions-scala-vs-java-8/

Lambda Expression in Java

Lambda Expression is way to passing a block of code to a method. To understand this concept we need to implement the functional interface and anonymous class which was used in the earlier version of the Java.

“Lambda Expression term is come from Mathematics, Greek letter Lambda basically associated with some kind of analogous situation where we are passing one function as a parameter to another function.”

package lambdaexpession;
interface Executable {
  void execute();
}

class Runner {
  public void run(Executable e) {
    System.out.println("Executing Code Block…");
    e.execute();
  }
}

public class App {
  public static void main(String args[]) {
    Runner runner = new Runner();
    runner.run(new Executable() {
      public void execute() {
        System.out.println("Anonymous Class Code Block.");
      }
    });
  }
}

The output of above code is

Executing Code Block…
Anonymous Class Code Block.

same thing we can implement with the help of Lambda Expression in following manner,
we need to replace above mentioned anonymous class code block

runner.run(new Executable() {
  public void execute() {
    System.out.println("Anonymous Class Code Block.");
  }
});

with following Lambda Expression,

runner.run( () -> System.out.println("Lambda Expression Code Block. "));

we get same output from Lambda Expression, i.e.

Executing Code Block…
Lambda Expression Code Block.

Hence by using Lambda Expression in Java, we are reducing code complexity and increasing the readability of our application.
Hope, you will get basic idea of Lambda Expression by above mentioned example. Below are some important points which will help you to clear understanding of Lambda Expressions in Java 8.

A) We can replace the Anonymous class with our Lambda Expression.
The below mentioned method

runner.run( () -> System.out.println("Lambda Expression Code Block."));

is replaced the whole anonymous class which is mentioned in above example. i.e.

runner.run(new Executable (){
  public void execute(){
    System.out.println("Anonymous Class Code Block.");
  }
});

where,

runner.run( () -> System.out. ("Lambda Expression Code Block."));

method name which is declared in Runner class.
List of Parameters required for Lambda Expression.
Code block which to be executed.

B) If we want to execute a multiple statements with the Lambda Expression then include the { and } parenthesis to code which you need to be executed. If you are adding multiple statements then it is mandatory to terminate the each statement with the “;”. If you are using { and } parenthesis and you have added single statement only then that single statement is also needs to be terminated with the help of “;”.

runner.run( () -> {
  System.out.println("Lambda Expression Code Block.");
  System.out.println("This is another Statement");
});
  • So, Lambda Expression of rows are associated with interface having single method in it.
  • With the help of Lambda Expression, we are simplifying the syntax for passing actual code to the another method/function.
  • In Java 8, if interface consist of single method in it, then it will refer as functional interface. hence “Interface having single method is called as Functional Interface”.
    exa. Comparable and Runnable interface.
  • C) If we want return value from block of code that is going to be execute,

    package lambdaexpession;

    interface Executable{
      int execute();
    }

    class Runner{
      public void run(Executable e){
        System.out.println("Executing Code Block…");
        int value = e.execute();
        System.out.println("Return value is : "+value);
      }
    }

    public class App{
      public static void main(String args[]){
        Runner runner = new Runner();
        runner.run(new Executable (){
          public int execute(){
            System.out.println("Anonymous Class Code Block.");
            return 7;
          }
        });
      }
    }

    output of above example is,

    Executing Code Block…
    Anonymous Class Code Block.
    Return value is : 7

    same thing we can implement with the help of Lambda Expression in following manner,

    runner.run( () -> {
      System.out.println("Lambda Expression Code Block.");
      return 8;
    });

    Hence, if we replace the above code in our example then we get following output after execution of program,

    Executing Code Block…
    Lambda Expression Code Block.
    Return value is : 8

    D) If we are returning only literal value from Lambda Expression then no need to mentioned the datatype of return value.

    runner.run( () -> 8 );

    E) If we want to pass parameter,

    package lambdaexpession;

    interface Executable {
      int execute(int a);
    }

    class Runner {
      public void run(Executable e) {
        System.out.println("Executing Code Block…");
        int value = e.execute(12);
        System.out.println("Return value is : " + value);
      }
    }

    public class App {
      public static void main(String args[]) {
        Runner runner = new Runner();
        runner.run(new Executable() {
          public int execute(int a) {
            System.out.println("Anonymous Class Code Block.");
            return 7 + a;
          }
        });
      }
    }

    For above mentioned program, we get following output,

    Executing Code Block…
    Anonymous Class Code Block.
    Return value is : 19

    same thing we can implement with the help of Lambda Expression in following manner,

    runner.run( (int a) -> {
      System.out.println("Lambda Expression Code Block.");
      return 7+a;
    });

    we will get following output if we replace anonymous class with our Lambda Expression,

    Executing Code Block…
    Lambda Expression Code Block.
    Return value is : 19

    F) If we are using Lambda Expression then there is no need to define parameter type. Our Compiler will autodetect the type of parameter from the declaration of method from calling class.

    runner.run( (a) -> {
      System.out.println("Lambda Expression Code Block.");
      return 7+a;
    });

    G) In case of method overloading, we need to specify the datatype of parameters to avoid the ambiguity between overloading methods.

    package lambdaexpession;

    interface Executable{
      int execute(int a);
    }

    interface StringExecutable{
      int execute(String a);
    }

    class Runner{
      public void run(Executable e){
        System.out.println("Executing Code Block…");
        int value = e.execute(12);
        System.out.println("Return value is : "+value);
      }
     
      public void run(StringExecutable e){
        System.out.println("Executing Code Block…");
        int value = e.execute("Hello");
        System.out.println("Return value is : "+value);
      }
    }

    public class App{
      public static void main(String args[]){
        Runner runner = new Runner();
        runner.run(new Executable (){
          public int execute(int a){
            System.out.println("Anonymous Class Code Block.");
            return 7 + a;
          }
        });
      }
    }

    so after execution of this code, we will get following output,

    Executing Code Block…
    Anonymous Class Code Block.
    Return value is : 19

    same thing we can implement with the help of Lambda Expression in following manner,

    runner.run( (int a) -> {
      System.out.println("Lambda Expression Code Block.");
      return 7+a;
    });

    so after replacing and executing of our Lambda Expression, we will get following output,

    Executing Code Block…
    Lambda Expression Code Block.
    Return value is : 19

    H) If we have single parameter then no need to define the datatype of parameter as well as no need to add parenthesis for parameters.

    runner.run( a -> {
      System.out.println("Lambda Expression Code Block.");
      return 7+a;
    });

    I) If we want to pass multiple parameters then we need to add parenthesis compulsory.

    runner.run( (a,b) -> {
      System.out.println("Lambda Expression Code Block.");
      return a+b;
    });

    J) If we want to access the variable from main (parent) method in the block of Lambda Expression.

  • If we want to access variable from calling method in the anonymous class then it should be final for previous version of Java. But in Java 8, it is not mandatory to declare that variable as final.
  • But if we are re-assigning the value of that variable then compiler will throw Compile time Exception.
  • Means if we are not re-assigning value to variable in calling method then it is treated like final variable but it is not actually final variable, we can called it as effectively final variable.
  • public class App{
      public static void main(String args[]){
        int c = 100;
        // c=8; mustn’t do this.
        Runner runner = new Runner();
        runner.run(new Executable (){
          public int execute(int a, int b){
            System.out.println("Anonymous Class Code Block.");
            return a+b+c;
          }
        });
      }
    }

    same thing we can implement with the help of Lambda Expression in following manner,

    runner.run( ( a,b ) -> {
      System.out.println("Lambda Expression Code Block.");
      return a+b+c;
    });

    K) Lambda Expression doesn’t have their own scope, so we can access variable from calling method, while in previous version of Java, anonymous class having their own scopes, so you can re-declare the variable with same declaration as declared in the parent method.
    This variable in the anonymous class is treated as new variable.

    public class App{
      public static void main(String args[]){
        int d = 77;
        Runner runner = new Runner();
        runner.run(new Executable (){
          public int execute(int a, int b){
            System.out.println("Lambda Expression Code Block.");
            //int d=8; can do this in anonymous classes.
            return a+b+c;
          }
        });
      }
    }

    same thing we can implement with the help of Lambda Expression in following manner,

    runner.run( ( a,b ) -> {
      System.out.println("Lambda Expression Code Block.");
      //int d=5; we can’t do this as this is no new scope.
      return a+b+c;
    });

    L) We can store all the Lambda Expression into equivalent object also.

    Executable ex = (a,b) -> {
      System.out.println("Lambda Expression Code Block.");
      return a+b;
    }
    runner.run(ex);

    M) We can assign the Lambda Expression to superclass of interface, for that we need to typecast that object to superclass object type.

    Object codeBlock = (Executable) (a,b) -> {
      System.out.println("Lambda Expression Code Block.");
      return a+b;
    }

    This is very useful to implement comparable interface.

    So this is some basic and simple Lambda Expressions which is used in Java 8. We will see some real time examples of Lambda Expressions in our Next Post.

    Hope this blog will help you to understand the basic concept of Lambda Expressions in Java 8.
    Please don’t forget to comment your feedback for this post. 🙂

    References : Video of Cave of Programming.