Free Online Courses for Software Developers - MrBool
× Please, log in to give us a feedback. Click here to login
×

You must be logged to download. Click here to login

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

Understanding Java 8 Lambda Expressions

Lambdas are introduced to reduce the bulky code overhead of an anonymous class. In this article we will learn what anonymous class and lambda expressions are and what was the need of introducing lambda expressions in Java.

Understanding Java 8 Lambda Expressions

Java 8 was released in 2014 introducing some amazing new features, including new streaming API, new APIs for date time manipulation, and JavaScript Engine Nashorn. Lambda expressions were also introduced in this new release and are considered Java’s first step into functional programming. These expressions were presented to eliminate overhead found while using anonymous class. This overhead can be a constructor or additional syntactical code. Lambda expressions were also introduced to eliminate the need of using anonymous class.

Oracle defines Lambda Expressions in this way:

One issue with anonymous classes is that if the implementation of your anonymous class is very simple, such as an interface that contains only one method, then the syntax of anonymous classes may seem unwieldy and unclear. In these cases, you're usually trying to pass functionality as an argument to another method, such as what action should be taken when someone clicks a button. Lambda expressions enable you to do this, to treat functionality as method argument, or code as data.”

Need of Lambda Expressions in Java

Lambdas are introduced to reduce the bulky code overhead of an anonymous class. In this article we will learn what anonymous class and lambda expressions are and what was the need of introducing lambda expressions in Java.

Anonymous class

An anonymous class is a local class without a name. The class gets declared and instantiated at the same time.

Lambda Expressions

Even for effortless operations, additional syntactical code is to be written each time with anonymous classes. So, the main concern with the anonymous class is its unclear, bulky code i.e., overhead. Lambda expressions eliminate the need of using an anonymous class. It is a functional interface with a single method only. These expressions also provide a powerful, functional programming capability to Java.

In this example, we will see why lambdas were introduced.

As we all have used the popular functional interface java.lang.Runnable, we know only a single method is declared in Runnable interface i.e., void run() . If you have worked on creating a thread before, you will know the start() function is required to initialize the running of a thread. The start() method then calls for the run() method.

The example below is shown using lambda expressions: () -> System.out.println("Thread running ") is our lambda expression.

new Thread(
      () -> System.out.println("Thread running ")
).start();

Below is an anonymous class, bulky and unclear code in comparison with the above code.

public class Demo {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                 System.out.println("Thread running”);
            }
       }).start();
   }
}

The overhead is less while using lambda expressions. That is why the introduction of lambda expressions is considered one of the prime features of Java 8.

Now, let us focus on what a functional interface is and how it is related to lambda expressions.

Functional Interfaces

In this section we will discuss what functional interfaces are, the role of @FunctionalInterface annotation, java.util.function package for Java 8, and how a functional interface is related to lambda expressions.

Let’s start with functional interfaces.

What is a Functional Interface

An interface is similar to a class in Java and a reference type. All of the methods in an interface are abstract, so a collection of abstract methods is also called an interface. A functional interface is an interface with only one abstract method declared. Below is a simple code snippet.

Department is our interface and DeptInfo is the single abstract method.

interface Department {
   // Single abstract method DeptInfo
   void DeptInfo(Collection collection);
}

Role of @FunctionalInterface Annotation

o The role of a new annotation is definitely a topic to discuss. One may ask, what was the need of introducing a new annotation? Verifying the functional interface isn’t necessary, because a compiler will do it on its own. But, still it is suggested to specify @FunctionalInterface annotation to reduce the workload, just like the @Override annotation in earlier versions of Java.

If you already know that you’re going to use lambda expressions, annotate the interface with @FunctionalInterface.

Department is our interface and DeptInfo is the single abstract method, but we have also used the annotation @FunctionalInterface .

@FunctionalInterface
interface Department {

   // single abstract method DeptInfo
   void DeptInfo (Collection collection);
}

Java 8 has defined a lot of functional interfaces to be used comprehensively in lambda expressions. Functional interfaces are defined in java.util.Function package discussed below.

Package java.util.function

With the introduction of Java 8, a new package was added containing functional interfaces commonly used for lambda expression and method reference. The newly introduced package is java.util.function. Two of the interfaces are explained below.

BiConsumer

Because it is a functional interface, BiConsumer can be used as a target type for a lambda expression or a method reference. It represents an operation that accepts two input arguments and returns no result.

The parameters are:

  • T - the type of the first argument to the operation.
  • U - the type of the second argument to the operation.

Syntax

@FunctionalInterface
public interface BiConsumer

Function

Function , also a functional interface, can be used as a target type for a lambda expression, or a method reference. It represents a function that accepts one argument and produces a result.

The parameters are:

  • T - the type of the input to the function.
  • R - the type of the result of the function.

Syntax

@FunctionalInterface
public interface Function

For the complete list, refer to the officialOracle Java Docs.

Lambda Expressions Structure in Java

The syntax of lambda expressions is different from what we have generally followed in Java. The general way is given below.

(argument1, argument2...) -> { body }
(type1 arg1, type2 arg2...) -> { body }

Here, argument1 and argument2 are arguments, type1 and type2 are their types i.e., data types -> is an Arrow Token

For example:

(p, q) - > p + q
(int p, int q) -> p + q

The structure shown above has the following parts:

Arrow (->) token

parameter -> body

Argument List

A lambda expression can contain zero or more arguments.

Zero Argument

// zero argument
() -> { System.out.println("Zero argument"); } 

One Argument

// only one argument
(int argument1) -> { System.out.println("Single integer argument- " + argument1); }

// takes a string ‘s’ and prints its value
(String s) -> System.out.println(s) 

Two Arguments

More than one argument is separated by a comma (,) operator.

// Two arguments
(int argument1, String argument2) -> { System.out.println("Argument First: " + argument1 + " and Argument Second: " + argument2); }

Note: The argument type (data type) can be eliminated while passing it to lambda expressions. That means (int x) and (x) are same i.e., it is optional to mention data type.

For example, both of them will work correctly.

(x, y) -> x + y
(int x, int y) -> x + y

Note: You can eliminate the () in the case of a single argument, if its type is inferred.

For example:

a -> a;
x -> 2 * x // gets x and returns the value of 2 * x

Argument Types

Here’s the type Dept of the parameter d ,

(Dept d) -> System.out.println("Employee salary: " + d.getSal()); 

Body

The body of the lambda expressions can contain zero, one or more statements.

Therefore, we can conclude that, the following are optional in lambda expressions structure: curly braces, return statement, type declaration, and parentheses around a single argument.

Example

Let’s move further using a working example to understand how different forms of lambda expressions can be used in a Java program. Below, I have created a class and in which I am performing an addition and multiplication operation.

We have used the rules for creating lambda expressions, which includes type int declaration and type int declaration with a return statement. It also shows how we can eliminate the () in the case of a single argument, if its type is inferred.

Here’s the complete code:

public class LambdaExp {

   interface Calculate {
       int operation(int p, int q);
   }

   interface Display {
       void DisplayMessage(String msg);
   }

   private int operate(int p, int q, Calculate calc){

      return calc.operation(p, q);
   }

   public static void main(String args[]){

      LambdaExp lExp = new LambdaExp();

      // type int declaration
      Calculate multiply = (int p, int q) -> p * q;

      // type int declaration - return statement with curly braces
      Calculate add = (int p, int q) -> { return p + q; };    

      // with parenthesis
      Display msg1 = (msg) -> System.out.println("Operation: " + msg);      
      msg1.DisplayMessage("Multiply two numbers:");
      System.out.println("6 x 12 = " + lExp.operate(6, 12, multiply));

      /* Without parenthesis - you can eliminate the () in case of a   
         single argument, if its type is inferred */
      Display msg2 = msg -> System.out.println("Operation: " + msg);
      msg2.DisplayMessage("Add two numbers:");
      System.out.println("6 + 12 = " + lExp.operate(6, 12, add));

   }
}

In the following image you can see the output for class LambdaExp, I have run it on Java 8 Online compiler.

Figure 1. Output

Observe that the class LambdaExp has two interfaces: Calculate and Display . Both of the interfaces have a single method in them: operation() and DisplayMessage() . The operation() method performs addition and multiplication, whereas the DisplayMessage() function prints the message to the console.

Various types of lambda expressions define the operation() method of Calculate interface. Then we have defined the implementation of DisplayMessage() method of interface Display.

Here, for multiplication, we wrote the following that had int type declaration:

Calculate multiply = (int p, int q) -> p * q;

The above can also be written without type int i.e.,

Calculate multiply = (p, q) -> p * q;

Here, for addition, we wrote the following that had a return statement with curly braces:

Calculate add = (int p, int q) -> { return p + q; }; 

We can also write the above without curly braces and without a return statement:

Calculate add = (int p, int q) -> p + q; 

Variable Capture

Variable capture occurs when a lambda expression try to use a local variable from its enclosing scope. However, this variable can only be used and should not be modified. Modifying it will cause an error since these variable are effectively final . The effectively final variable is a term which means that a variable whose value is never modified, once it is assigned initially.

Considering a snippet from the above example, we will add a local variable a and will modify it too. Modifying it will give an error, here's some part of the program we modified for our example on variable capture ,

public class LambdaExp {

   interface Calculate {
       int operation(int p, int q);
   }

   interface Display {
       void DisplayMessage(String msg);
   }

   private int operate(int p, int q, Calculate calc){

      return calc.operation(p, q);
   }

   public static void main(String args[]){

      int a = 10;

      LambdaExp lExp = new LambdaExp();

      // type int declaration
      Calculate multiply = (int p, int q) -> p * q + a;

      // this will give an error: local variables referenced from a lambda expression must be final or effectively final
      //  a--;
      // the program is the same as shown above, we just included a snippet of the same to show the error

Here, a is effectively final, so we used and added,

 Calculate multiply = (int p, int q) -> p * q + a;

But, modifying it will give an error and the program won't compile. Here, we decrement the variable a by a-- , which means we're modifying it and as we mentioned it is illegal, so the following error is thrown, since it will remove the effectively final status from variable a ,

Error - local variables referenced from a lambda expression must be final or effectively final

Here's the screenshot of the online compilation for the above program,

Figure 2. Output showing compile time error

Exception Handling

The concept of exception handling in any programming language is important and lambda expressions in Java also has a concept of handing exceptions. If checked exception is thrown, then the exception should be compatible with the exception listed. These excpetions are listed in the throws clause of the abstract method in the functional interface (shown in example below).

Here's a code snippet in which we have created a custom exception, MyException . In the class, we are calculating the sum, but while passing a zero-length array, it throws an exception with the message, " Exception! The array is empty! ". The exception is listed under the throws clause of calc() function, which is declared inside the functional interface SumCalc .

interface SumCalc {
  int calc(int[] s) throws MyException;
}
class MyException extends Exception {

  // This is our custom exception
  MyException() {
    super("Exception! The array is empty!");
  }
}
public class ExceptionHandling {
  public static void main(String args[]) throws MyException
  {
    int[] a = { 15, 18, 12, 76, 64, 35 };

     SumCalc num = (s) ->  {

      int sum = 0;
      if(s.length == 0)
        throw new MyException();

      // calculating the sum of numbers 
      for(int i=0; i < s.length; i++)
        sum +=s[i];
        return sum;
    };

    // The following statement finds the sum
    System.out.println("Sum of numbers= " + num.calc(a));

    // The following statement will throw an exception
    System.out.println("Value = " + num.calc(new int[0]));
  }
}

Figure 3. Online compiler showing output with custom exception

Final Words

Lambda expressions were introduced in Java 8 to make it easier for developers to write clean and clear code. Anonymous class implementation is easy, but the syntax may seem bulky. Lambda utilizes a light-weight mechanism reducing overhead and eliminating the need of using anonymous classes.



Have done Masters in Computer Applications (MCA) and currently working as a Website Developer, Software Developer and Technical Writer. Have successfully delivered various assignments while working as a Freelancer Technical Writer...

What did you think of this post?
Services
[Close]
To have full access to this post (or download the associated files) you must have MrBool Credits.

  See the prices for this post in Mr.Bool Credits System below:

Individually – in this case the price for this post is US$ 0,00 (Buy it now)
in this case you will buy only this video by paying the full price with no discount.

Package of 10 credits - in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download few videos. In this plan you will receive a discount of 50% in each video. Subscribe for this package!

Package of 50 credits – in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download several videos. In this plan you will receive a discount of 83% in each video. Subscribe for this package!


> More info about MrBool Credits
[Close]
You must be logged to download.

Click here to login