Java 8 Lambda Expressions
Lambda Expressions, a new language feature, has been introduced in Java 8. They enable you to treat functionality as a
method argument, or code as data. Java is a strong object oriented language. Apart from primitive types, everything in java are objects.
You need object references to invoke any method calls. Now, think about Java script, we can define functions any where you want,
you can assign functions to any variables, and you can pass functions as an input parameters to a method. It is called functional
programming language. As of now, Java don’t support functional programming. But Lambda expressions introducing functional programming
to Java. In java, lambda expressions are similar to functional programming, but not 100%.
Is it no clear? Lets start with an example.
package com.java2novice.lambda;
public class FirstLambdaExp {
public static void main(String a[]){
// create a thread with old way of java programming.
// CASE - 1
new Thread(new Runnable(){
public void run(){
System.out.println("In run method, without lambda expression");
}
}).start();
// now create the above code using lambda expression.
// CASE - 2
new Thread(() -> System.out.println("In run method, lambda expression")).start();
}
}
|
In the above code, we are instantiating a Threat using Runnable interface. In the CASE - 1, we are creating a Thread object
by passing Runnable interface implementation class as anonymous class. In the CASE - 2, we are using Lambda expressions in the place of
anonymous class. Both servers the same purpose.
Lambda expression is an anonymous function with out any declarations. You can not find any access specifies, return types, and
not even method name. In the above example, if you closely monitor, we are passing run() method as an argument to Thread constructor. As I
said, it is an anonymous function, you can write it directly where you are going to use it.
Let's see the syntax of Lambda expression:
Here arguments are similar to method arguments, you can either define arguments type or simply you can pass value. The type
of the parameters can be explicitly declared or it can be inferred from the context. Also, you can have any number of arguments, or no
arguments. Incase, if there is only one parameter, and type is not specified, then parentheses are optional.
For example:
() -> {System.out.println("No arguments");}
(int i) -> {System.out.println(i);}
(i) -> {System.out.println(i);}
(int I, int j) -> {System.out.println(i+j);}
i -> {System.out.println(i);}
|
The lambda expression body can contain any number of statements, or no statement also. Curly braces are mandatory if the body
contains more than one statement, it is optional, if body has only one statement.
(int i, int j) -> return i+j
(int i, int j) -> {
int i = i+j;
System.out.println(i);
}
|
You don’t need to define return type explicitly, it infers the type. If you don’t specify return, void will be the default
behavior. If you have only one statement, and if you didn’t specify the return type, the statement value will be returned back.
What is Functional Interface?
You can use lambda expressions with the interfaces which has only one abstract method. An interface with only one abstract method
is called functional interface. You know marker interface, which doesn't have any abstract methods in it. It is an empty interface, and used to
notify compiler. Similarly, in Java 8, you can define functional interfaces with @FunctionalInterface annotation to notify java compiler. If you
annotate an interface with this annotation, and if you define more than one abstract methods in it, then compiler will throw an error.
Lambda expression works on functional interface. Let's see another example with functional interface. We will use one of the functional
interfaces for our example, defined in Java 8 util package, it is BinaryOperator. The code is as given below:
public interface BinaryOperator<T> {
T apply(T left, T right);
}
|
package com.java2novice.lambda;
import java.util.function.BinaryOperator;
public class LambdaExpressEx {
public static void main(String a[]){
int i = 10;
int j = 5;
int sum = calculate(i, j, (i,j) -> {return (i+j);} );
System.out.println("Sum:"+sum);
int sub = calculate(i, j, (i,j) -> {return (i-j);} );
System.out.println("Subtraction:"+sub);
}
public static int calculate(int i, int j, BinaryOperator<Integer> bo){
return bo.apply(i, j);
}
}
|
Look at the above implementation using lambda expression, We are not creating implementation class for BinaryOperator on every call to
calculate method . Instead we are passing method implementation.
In this article, we are providing basic understanding of Lambda expressions, there are many other usages with List, Streams. We will
cover this in the next articles.
|