Java 8 – Lambda Expression and Functional Interface | Code Factory


Index Page : Link

Donate : Link

Medium Blog : Link

Applications : Link

What is Lambda (λ) Expression? How to write Lambda (λ) Expression?

– It is Anonymous function, not having name, not having modifier, not having any return type

e.g.1

() -> { System.out.println("Code Factory"); }

e.g.2

// Normal Method :
public void add(int a, int b) {
	System.out.println(a + b);
}

//Lambda Expression :
(int a, int b) -> { System.out.println(a + b); }

e.g.3

// Normal Method :
public int getLength(String s) {
    return s.length();
}

//Lambda Expression :
(String s) -> { return s.length(); }

– In the Lambda (λ) Expression body, if only one statement is there then curly braces ({}) are optional

e.g.1

// Normal Method :
public void m1() {
    System.out.println("Code Factory");
}

//Lambda Expression :
() -> { System.out.println("Code Factory"); }
            OR
() -> System.out.println("Code Factory");

e.g.2

// Normal Method :
public void add(int a, int b) {
	System.out.println(a + b);
}

//Lambda Expression :
(int a, int b) -> { System.out.println(a + b); }
          OR
// Below statement also called Type Inference
(a, b) -> System.out.println(a + b);

e.g.3

// Normal Method :
public int getLength(String s) {
	return s.length();
}

//Lambda Expression :
(String s) -> { return s.length(); }
          OR
(s) -> return s.length();
          OR
(s) -> s.length()
          OR
s -> s.length()

Characteristics/Properties of Lambda (λ) Expression :

(1) A λ-Expression can take any number of parameter

e.g.

() -> System.out.println("Code Factory");
(s) -> s.length();
(a, b) -> System.out.println(a + b);

(2) If multiple parameters present then there parameters shouls be seperated with comma (,)

e.g.

(a, b) -> System.out.println(a + b);

(3) If only one parameters available then parenthesis are optional

e.g.

(s) -> s.length(); TO s -> s.length();

(4) Usually we can specify the type of parameters of compiler expect the type based on context, then we can remove type, called type inference

e.g.

(int a, int b) -> System.out.println(a + b);
          TO
(a, b) -> System.out.println(a + b);

(5) Similar to method body, λ-Expression body can contain any number of statements. If multiple statements are there then we should enclose within curly braces

e.g

() -> {
    stmt1;
    stmt2;
}

(6) If body contains only one statement then curly braces are optional

e.g

() -> System.out.println("Code Factory");

(7) If λ-Expression return something then we can remove return keyword

e.g

s -> s.length();

Functional Interface :

– Interface which contains only single/one abstract method is called Functional Interface

e.g.

Runnable        ->   contains only run() method
Callable        ->   contains only call() method
ActionListener  ->   contains only actionPerformed() method
Comparable      ->   contains only compareTo() method

– Functional Interface may have any number of default and static methods, restriction is only applicable for abstract method.

// right Functional Interface              ✓
interface Interf {
    public void m1();
    default void m2() { }
    public static void m3() { }
}

// wrong Functional Interface              X
interface Interf {
    public void m1();
    public void m2();
}

@FunctionalInterface :

(1)

// valid                            ✓
package com.codeFactory.lambdaExpression;

@FunctionalInterface
interface Interf {
	public void m1();
	default void m2() { };
	public static void m3() { };
}

(2)

// not valid                        X
package com.codeFactory.lambdaExpression;

@FunctionalInterface
interface Interf {
	public void m1();
	public void m2();
}

/*
Unexpected @FunctionalInterface annotation
@FunctionalInterface
^
  Interf is not a functional interface
    multiple non-overriding abstract methods found in interface Interf
1 error
*/

(3)

// not valid                      X
package com.codeFactory.lambdaExpression;

@FunctionalInterface
interface Interf {
	
}

/*
Unexpected @FunctionalInterface annotation
@FunctionalInterface
^
  Interf is not a functional interface
    no abstract method found in interface Interf
1 error
*/

Functional Interface with inheritance :

(1) If an interface extends Functional Interface and child interface does not contain any abstract method, then child interface is always Functional Interface

// valid     ✓
package com.codeFactory.lambdaExpression;

@FunctionalInterface
interface InterfP {
	public void m1();
}

@FunctionalInterface
interface InterfC extends InterfP {
	
}

(2) In the child interface, we can define exactly same parent interface abstract method

// valid     ✓
package com.codeFactory.lambdaExpression;

@FunctionalInterface
interface InterfP {
	public void m1();
}

@FunctionalInterface
interface InterfC extends InterfP {
	public void m1();
}

(3) In the child interface we can’t define any new abstract methods otherwise we will get CE

// not valid     X
package com.codeFactory.lambdaExpression;

@FunctionalInterface
interface InterfP {
	public void m1();
}

@FunctionalInterface
interface InterfC extends InterfP {
	public void m2();
}

/*
Unexpected @FunctionalInterface annotation
@FunctionalInterface
^
  InterfC is not a functional interface
    multiple non-overriding abstract methods found in interface InterfC
1 error
*/

(4) Child interface is normal interface so it will successfully compile

// valid     ✓
package com.codeFactory.lambdaExpression;

@FunctionalInterface
interface InterfP {
	public void m1();
}

interface InterfC extends InterfP {
	public void m2();
}

Invoking Lambda Expression By using Functional Interface :

(1)

without λ-Expression :

package com.codeFactory.lambdaExpression;

interface Interf {
	public void m1();
}

class Demo implements Interf {
	public void m1() {
		System.out.println("m1() method implementation");
	}
}

public class Test {
	public static void main(String... args) {
		Interf i = new Demo();
		i.m1();
	}
}

with λ-Expression :

package com.codeFactory.lambdaExpression;

interface Interf {
	public void m1();
}

public class Test {
	public static void main(String... args) {
		Interf i = () -> System.out.println("m1() method implementation");
		i.m1();
	}
}

(2)

without λ-Expression :

package com.codeFactory.lambdaExpression;

interface Interf {
	public void add(int a, int b);
}

class Demo implements Interf {
	public void add(int a, int b) {
		System.out.println(a + b);
	}
}

public class Test {
	public static void main(String... args) {
		Interf i = new Demo();
		i.add(10, 20);
		i.add(100, 200);
	}
}

with λ-Expression :

package com.codeFactory.lambdaExpression;

interface Interf {
	public void add(int a, int b);
}

public class Test {
	public static void main(String... args) {
		Interf i = (a, b) -> System.out.println(a + b);;
		i.add(10, 20);
		i.add(100, 200);
	}
}

(3)

without λ-Expression :

package com.codeFactory.lambdaExpression;

interface Interf {
	public int getLength(String s);
}

class Demo implements Interf {
	public int getLength(String s) {
		return s.length();
	}
}

public class Test {
	public static void main(String... args) {
		Interf i = new Demo();
		System.out.println(i.getLength("Code"));
		System.out.println(i.getLength("Factory"));
	}
}

with λ-Expression :

package com.codeFactory.lambdaExpression;

interface Interf {
	public int getLength(String s);
}

public class Test {
	public static void main(String... args) {
		Interf i = (s) -> s.length();
		System.out.println(i.getLength("Code"));
		System.out.println(i.getLength("Factory"));
	}
}

(4)

without λ-Expression :

package com.codeFactory.lambdaExpression;

class MyRunnable implements Runnable {
	@Override
	public void run() {
		for(int i=0; i<5; i++) {
			System.out.println("Child Thred.");
		}
	}
}

public class Test {
	public static void main(String... args) {
		Runnable r = new MyRunnable();
		Thread t = new Thread(r);
		t.start();
		for(int i=0; i<5; i++) {
			System.out.println("Main Thred.");
		}
	}
}

with λ-Expression :

package com.codeFactory.lambdaExpression;

public class Test {
	public static void main(String... args) {
		Runnable r = () -> {
			for(int i=0; i<5; i++) {
				System.out.println("Child Thred.");
			}			
		};
		Thread t = new Thread(r);
		t.start();
		for(int i=0; i<5; i++) {
			System.out.println("Main Thred.");
		}
	}
}

Functional Interface Summary :

(1) It should contains exactly one abstract method (SAM : Single Abstract Method)

(2) It can contains any number of default and static methods

(3) It acts as a type for λ-Expression

e.g.  Interf i = () -> System.out.println("Code Factory");
       -----------      -------------------------------
           type                λ-Expression

(4) It can be used to invoce λ=Expression

e.g. i.m1()

. . . . .

Case 1 : Why Funtional Interface should contains only one abstract method?

– Purpose of Functional Interface is to invoke/call Lambda (λ) Expression. Lambda (λ) Expression should map to method of interface. So interface contain none or multiple abstract method then there is a problem in mapping thats why functional interace contains only one abstract method.

Case 2 : What is the advantage of @FunctionalInterface annotation?

– To provide extra information.

12 thoughts on “Java 8 – Lambda Expression and Functional Interface | Code Factory”

  1. I absolutely love your blog and find almost all of your post’s to be exactly I’m looking for. Do you offer guest writers to write content available for you? I wouldn’t mind writing a post or elaborating on a few of the subjects you write about here. Again, awesome web site!

    Liked by 1 person

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s