0% found this document useful (0 votes)
6 views13 pages

Java 8 Lambda Expression

Lambda expressions in Java are used with functional interfaces, allowing for concise anonymous functions that can be passed as arguments. They simplify code by eliminating the need for separate classes or clumsy anonymous inner classes for single-method interfaces. Java 8 introduced built-in functional interfaces, such as Predicate, Function, and Consumer, to facilitate functional programming, while also providing primitive functional interfaces to enhance performance with primitive types.

Uploaded by

bond64192
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views13 pages

Java 8 Lambda Expression

Lambda expressions in Java are used with functional interfaces, allowing for concise anonymous functions that can be passed as arguments. They simplify code by eliminating the need for separate classes or clumsy anonymous inner classes for single-method interfaces. Java 8 introduced built-in functional interfaces, such as Predicate, Function, and Consumer, to facilitate functional programming, while also providing primitive functional interfaces to enhance performance with primitive types.

Uploaded by

bond64192
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

Lambda Expressions

Why or When can we use Lambda expressions ?

Lets say we have an interface which has exactly one abstract method (i.e, functional
interface) then only we can use the lambda expressions.

What or Syntax of Lambda Expression ?

Lambda expression is an anonymous function that can be passed as an argument to a


method and is very concise to look.

Lets try to understand the essence of why should we use the lambda expressions
using an example.

Lets say we have a functional interface as follows

If we want to access this pay() method we previously used to have 2 approaches

1) Creating another class and implementing this interface as follows


and finally access this method in main using the object of this class as follows

2) Using the anonymous inner class as can be achieved as follows

Using the above approaches were follows before Java 8 but there are some dis
advantages with this as follows

with approach 1 we are always required to create a separate class to define the
method of functional interface what if the application has 100 of functional
interfaces then we have to create 100 classes just to provide the definition and
access which becomes cumbersome.
with approach 2 though we are able to achieve in the same file the code looks
clumsy and what if there are many abstract methods(not a functional interface)
and we just want to use 1 method at a specific place then also we have to provide
the implementation os unused methods which is waste of time, and also harder to
read.

So to overcome this challenges Java 8 introduced the Lambda Expressions to


achieve the functional programming
Syntax of Lambda Expression

(parameters) → {

// business logic

We can further simplify this lambda expression in the following scenarios

If the function is accepting only one parameter then we can remove () for the
parameters and reduce as follows

parameter → {

If the function has only one statement as the business logic we can even remove
the enclosing {} as follows

parameter → return [business logic]

If the function has only one statement and we wanted to return something we can
further get rid of the return keyword as follows

parameter → [business logic]

If there are no parameters then the () for the parameter is mandatory as follows

() → business logic

An illustration of how to convert any imperial method to lambda expression

Lets say we have a method which accepts 2 integers and return the sum of those 2
values

1) Normal Imperial way of method looks as follows


2) lambda expression or functional programming approach

(To use lambda the thumb rule is we have to have a functional interface ) so lets say
we have a functional interface as follows

And to use this sum method we can define the lambda expression as follows

Always the lambda expression is assigned to the Reference of the functional interface
and using that reference variable the abstract method is called in the case of having
our own custom functional interfaces.

We saw that functional programming is achieved through lambda expressions, but


also saw that lambda expressions are only possible for the functional interfaces.
Which means to write the business logic using the functional programming that means
we have to declare the functional interface for every method ? Hell No, here is where
the Java Inbuilt Functional Interfaces comes into handy.

For our convenience Java came up with the built in Functional Interfaces using which
we can easily write the business logic in the functional programming approach all of
them belongs to java.lang.function package

1) Java.lang.function.Predicate<T>

Usage - This can be used when ever we want to write the business logic which accepts
single parameter(of any type primitive or non primitive) and the function returns
boolean value.

Example - we want to see if the given number is even or not (if even return true or
false)

Using traditional approach Using the functional programming

To understand the above functional programming approach code it is essential to


understand what exactly is the Predicate<T>.
Predicate<T> is the functional Interface in the java.lang.function which has the
abstract method test(T t) which takes the input of any type and returns the boolean
value. The below given are the default and static methods present in the Predicate<T>

boolean test(T t) → As we saw this is the method which we use to invoke the
lambda expression
and(Predicate<T> other) → If there are more than one conditions to check we can
combine all the lambda expressions using the and default method which will
return the composite predicate (think this is same like logical and and evaluates
left to right and so said to be short circuiting as if first is false second does not
even execute)
or(Predicate<T> other) → same as the and but this works same as the logical or
operator (returns the short circuiting logical or composite predicate same as and)
negate() → returns the Predicate that represents the logical negation of the called
predicate (i.e true becomes false and vice versa)
isEqual(Object target) → this returns the Predicate which is object →
object.isEquals(target) so we can run the the test(T t) which executes this logic
with the input provided.

All the above mentioned are described in the below example


2) java.lang.function.Function<T,R>

Usage - When in the business logic if the method accepts 1 input of any type and
returns a value of any type then use the Function.

T → Input type

R → Return type

Example - lets say we are providing the input integer to the method and expecting
the square of that value then
Traditional way Functional programming

Here in the Function<T,R> we have an abstract method apply(T t) which takes the
mentioned input(T) and return the mentioned type ® and also there are some other
methods as folllows

R apply(T t) → Takes the input T and returns the value of Type R


compose(Function<V,T> before) → first the before will be evaluated and will be
composed with the caller Function.
andThen(Function<R,V> after) → Its the reverse of compose first the caller
Function will be executed and then the after Function.
identity() → It just returns the same Function which is passed . Normally used
when we want to get the same value as input.

All the discussed methods are demonstrated in the example below

3) java.lang.Function.UnaryOperator<T>

Usage - When the business logic has the requirement of having the same type of
parameter and return type then use UnaryOperator.

All the methods discussed above work exactly same for this UnaryOperator also

4) java.lang.Function.Consumer<T>

Usage - When the function only takes the input but does not return anything then use
the Consumer

Example - Lets say we want to append some string to the already presented string
and print it without returning as below
Traditional Approach Functional Programming

This Consumer<T> has the below methods

void accept(T t) → This is the abstract method in the Consumer functional


Interface which takes an input of any type but will not return any value;
andThen(Consumer<T> after) → This will return the composite Consumer where
the Caller Consumer will be executed first and then the passed parameter.

Below are the example demonstration for the same


4) java.lang.Function.Supplier<T>

Usage - When having a scenario where the function should not accept any input but
provides the output of given Type T.

Example - say we have business requirement of getting the OPT we no need to give
any input as follows.

Traditional Approach Functional Approach

This Supplier<T> (T here is the return type) has only one abstract method no
static and default methods here

get() → used to get the returned value

IMPORTANT NOTE - SAME AS THE ABOVE MENTIONED ALL FUNCTIONAL


INTERFACES WHERE EVERYTHING EXCEPT SUPPLIER TAKES 1 INPUT WE HAVE
INTERFACES WHICH TAKES THE 2 INPUTS ALSO BUT USAGE AND EVERYTHING
IS SAME (BUT THE STATIC AND DEFAULT METHODS PRESENT HERE FOR THESE
CHANGES SEE THE CLASS DOCUMENTATION). BUT THERE ARE NO
INTERFACES FOR MORE THAN 2 INPUTS. SO IF THE BUSINESS REQUIREMENT
HAS 3 PARAMETERS FOR ANY METHOD ONLY OPTION IS TO CREATE THE
CUSTOM FUNCTIONAL INTERFACE
1.

All the Functional Interfaces discussed earlier are accepting the input of type Object
(That is not the primitive type). But we worked with the primitive types in all the
examples. so what exactly happened ?

The primitive type before sent as the parameter is Auto Boxed to its Wrapper class
and is passed.
In the lambda when ever we are performing the operations the Wrapper class is
converted to the primitive type to support the computations
At last the primitive type is again converted to the wrapper class while returning
the computational output.

This way if we have a list of many primitive types and we peform lanbda expression
using the above functional interfaces all these steps needs to be performed which will
degrade the performance significantly so Java came up with the Primitive
Functional Interfaces.

Primitive Functional Interfaces In Java (just IntPredicate not


IntPredicate<T>)
1) For Predicate Functional Interface

java.util.function.IntPredicate - will always accept the int type and return boolean
java.util.function.DoublePredicate - will always accept the double and return
boolean
java.util.function.LongPredicate - will always accept the long and return boolean

2) For Function Functional Interface

java.util.function.IntFunction<R> - will always accept the int type and return the
specified type (R)
java.util.function.DoubleFunction<R> - will always accept the double type and
return specified type (R)
java.util.function.LongFunction<R> - will always accept the long type and return
specified type (R)
java.util.function.ToIntFunction<T> - will accept type T but always return int type
java.util.function.ToDoubleFunction<T> - will accept type T but always return
double type
java.util.function.ToLongFunction<T> - will accept type T but always return long
type
java.util.function.IntToDouble - will accept int and return double
Note - There are still many interfaces of same kind with the BiFunctional also but its
easy to identify with the naming convention of the interface

if prefix with To that means after To will be the return type

if not prefix with To that means it is the parameter type

3) For Consumer Functional Interface (no return type)

java.lang.function.IntConsumer - will only accepts int type and returns nothing


java.lang.function.DoubleConsumer - will only accepts double type and returns
nothing.
java.lang.function.ObjIntConsumer<T> - this is the part of the BiConsumer this
means accepts 2 parameters first is of any type and the second is always int.

4) For Supplier Functional Interface (no input type)

java.lang.function.IntSupplier - always return int type


java.lang.function.DoubleSupplier - always return double type
java.lang.function.LongSupplier - always return long type

5) For Unary Functional Interface (same input type and return value)

java.lang.function.IntUnaryOperator - 1 input of type int and return value of type


int.
java.lang.function.DoubleUnaryOperator - 1 input of type double and return value
of type double.
java.lang.function.LongUnaryOperator - 1 input of type long and return value of
type long.

You might also like