What is Lambda Expressions and its usage in Java 8?

Java 8 (version 1.8) release is notable due to bunch of new features it bring on board. Most of the core java language changes is for fitting Lambda Expression (also called closure) in the Eco System. Java already proved itself as one of the effective object-oriented language, with Lambda Expression in place it will be a great combination of object-oriented and functional style of coding.In this tutorial we will try describe concepts which will serve as the building blocks for the functional programming in Java 8.

Introduction to Lambda Expression

Lambda expression is way to define function or method without having any name. It enable us to encapsulate a single unit of behavior and pass it to other code. Lambda Expression make single method class expression more concise.
Lambda Expression made up of :
Lambda Parameters -> Lambda Body
For understanding how Lambda expression can be used we are presenting one example below.
Let say we want to make a calculator functionality. Go through the example and try to understand how Lambda Expression has been used or

/*
 * (C) Mrityunjay Kumar
 * File Name: Calculator.java
 */
package com.geekmj.lambdaexpressions.example2;

public class Calculator {

    /* Functional Interface */
    interface Calculation {
 int calculate(int number1, int number2); /* Only one abstract method */

 static void doNothingStaticMethod() {
 }; /* 1st Static Method */

 static void doNothingStaticMethod2() {
 }; /* 2nd Static Method */
    }

    /*
     * a method which takes 2 int and Calculation (functional interface)
     * implementing object
     */
    public int operateNumber(int number1, int number2, Calculation calc) {
 return calc.calculate(number1, number2);
    }

    /* Functional Interface */
    interface Name {
 void print(String name); /* Only one abstract method */

    }

    public void printName(String yourName, Name name) {
 name.print(yourName);
    }

    public static void main(String[] args) {
 Calculator aCalculator = new Calculator();

 /* Implementation for functional Interface using Lambda Expression Below */
 /* Lambda Expression : (param1, param2, ...) -> return somedata; */
 Calculation add = (a, b) -> a + b;
 Calculation subtract = (a, b) -> a - b;

 System.out.println("40 + 2 = " + aCalculator.operateNumber(40, 2, add));
 System.out.println("40 - 2 = " + aCalculator.operateNumber(40, 2, subtract));

 /* You can directly define the Lambda Expression in argument */

 System.out.println("40 * 2 = " + aCalculator.operateNumber(40, 2, (a, b) -> a * b));
 System.out.println("40 / 2 = " + aCalculator.operateNumber(40, 2, (a, b) -> a / b));

 /* You may can specify the data type of Lambda Expression Parameter */
 System.out.println("80 / 2 = " + aCalculator.operateNumber(80, 2, (int a, int b) -> a / b));

 /* You may can user return statement in Lambda Expression Body */
 System.out.println("80 / 2 = " + aCalculator.operateNumber(80, 2, (int a, int b) -> {
     return a / b;
 }));

 aCalculator.printName("Mrityunjay", name -> System.out.println("You are saying your name is " + name));

 // Compilation Error : aCalculator.printName("Ram", String name
 // ->System.out.println("You are saying your name is "+name));

 aCalculator.printName("Mrityunjay", (String name) -> System.out.println("You are saying your name is " + name));

 // void statement may or may not have parentheses

 aCalculator.printName("With Parentheses void Statement", (String someText) -> {
     System.out.println("You are saying " + someText);
 });

 aCalculator.printName("Without Parentheses void Statement/expession", (String someText) -> System.out.println("You are saying " + someText));
    }

}
Functional Interface: An Interface which have only one abstract method. It may can have one or more default or static methods.

A Lambda Expression can be used to implement functional interface inline (on the fly), without creating a class or implementing the method. In this way we can pass various Lambda expression (different implementation) for same functional interface in different contexts.
Calculation add = (a, b) -> a + b; is implementing calculate method of Calculation Interface on the fly.
Using Lambda Expression, we had successfully pass two different types of implementation for functional interface abstract method.
In System.out.println("40 * 2 = " + aCalculator.operateNumber(40, 2, (a, b)-> a * b)); statement (a, b)-> a * b) is on the fly functional interface implementation using Lambda Expression.
When we introduce second abstract method to Calculation Interface, it is no more a functional interface. When we try to use Lambda Expression for implementing non functional interface than compiler will throw error – “The target type of this expression must be a functional interface“.

Target type must be functional interface
Compile time error for non functional implementation of Lambda Expression

With the help of functional interface and Lambda Expression, we can pass function as a parameter from one method to another. This concept is known as closure. Many programming language like Java Script, Scala and others had already using it.

Lambda Expression Syntax

There are 3 parts of Lambda Expression:

  1. Parameters.
  2. Arrow token ->.
  3. Body; An expression or a statement.

Parameters

A comma separated list of parameters in parentheses. For Single argument we may remove parentheses. Few E.g.
<b><i>(a, b)</i></b> -> a * b : Parameters in bracket without data type.
<b><i>(int a, int b)</i></b> -> a * b : Parameters in bracket with data type.
<b><i>(int a, b)</i></b> -> a * b : It’s compilation token error. If one parameter have data type mentioned we have to mention it for all.
<i><b>a</b></i> -> System.out.println("Value " + a) : Single argument without parentheses.
<i><b>(a)</b></i> -> System.out.println("Value " + a) : Single argument with parentheses.
<i><b>(int a)</b></i> -> System.out.println("Value " + a) : Single argument with parentheses & data type.
-> System.out.println("No Argument Lambda Expression") : You can’t define Lambda Expression without any argument.

Arrow Token

-> arrow token is used to distinguish parameter from Body

 Body

It can be expression
<b><i>(a, b)</i></b> -> a * b  : Expression evaluated and value returned.
or
Statement
<b><i>(a, b)</i></b> -> { return a * b; } : return statement must be enclosed in brackets and it’s not expression.
name -> { System.out.println("Name " + name); } : void statement with parentheses
name -> System.out.println("Name " + name) : void expression without parentheses

Lambda expression use case

We had seen the way lambda expression can be use to implement functional interface.
In this section we will explore the changes bring by lambda expression in the java platform for carrying out various activity.

First and foremost change came in Java platform with the introduction of Stream.

A stream is a sequence of elements. Unlike a collection, it is not a data structure that stores elements. Instead, a stream carries values from a source through a pipeline

Let say we have a list of Person (Objects) and we want to print the email id of those Person whose age is greater than 17 and less than 25.

package com.geekmj.lambdaexpressions.example3;

import java.time.LocalDate;
/**
 *
 *  File name : Person.java
 */
public class Person {
    public enum Sex {
    MALE, FEMALE
    }

    String name;
    LocalDate birthday;
    Sex gender;
    String emailAddress;
    int age;

    public Person() {

    }

    public Person(String name, LocalDate birthday, Sex gender, String emailAddress, int age) {
    super();
    this.name = name;
    this.birthday = birthday;
    this.gender = gender;
    this.emailAddress = emailAddress;
    this.age = age;
    }
    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public LocalDate getBirthday() {
    return birthday;
    }

    public void setBirthday(LocalDate birthday) {
    this.birthday = birthday;
    }

    public Sex getGender() {
    return gender;
    }

    public void setGender(Sex gender) {
    this.gender = gender;
    }

    public String getEmailAddress() {
    return emailAddress;
    }

    public void setEmailAddress(String emailAddress) {
    this.emailAddress = emailAddress;
    }

    public void setAge(int age) {
    this.age = age;
    } 

    public int getAge() {
    return age;
    }
}
package com.geekmj.lambdaexpressions.example3;

/**
 *  This java code demonstrate the way we can use the Lambda Expression in Java 8
 * File Name : Example3Runner.java
 */
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

public class Example3Runner {

    public static void main(String[] args) {
    /* List Of Persons */
    List
 persons = new ArrayList
();
    persons.add(new Person("Ram", LocalDate.of(1982, 01, 11), Person.Sex.MALE, "[email protected]", 11));
    persons.add(new Person("Shyam", LocalDate.of(1984, 01, 11), Person.Sex.MALE, "[email protected]", 14));
    persons.add(new Person("Sita", LocalDate.of(1990, 01, 11), Person.Sex.FEMALE, "[email protected]", 17));
    persons.add(new Person("Gita", LocalDate.of(1992, 01, 11), Person.Sex.FEMALE, "[email protected]", 8));
    persons.add(new Person("Radha", LocalDate.of(1987, 01, 11), Person.Sex.FEMALE, "[email protected]", 18));

    /*
     * Printing List of Persons Whose Age is between 8 and 11
     */

    /* Using Aggregate Operations that accept Lambda Expression */
    System.out.println("*** Using Aggregate Operations which accept Lambada Expression to print the stuff ***");

    persons.stream().filter(p -> p.getGender() == Person.Sex.MALE && p.getAge() >= 8 && p.getAge() <= 18).map(p -> p.getEmailAddress())
        .forEach(email -> System.out.println(email));

    }
}

References:

  1. Lambda Expressions from Java Tutorial

Leave a Comment

Your email address will not be published. Required fields are marked *