Using Lambda Expressions in your Java Code.
All about making clearer and flexible code
As we know, JDK 1.8 is the game-changer in the Java ecosystem, which is shipped with a lot of improvements, a new rich set of functionalities in the existing java development system as wells as introduced new game-changing APIs.That’s Streams and Lambdas.
Throughout this article let us walk through the functional programming in java using a lambda expression.
Before going further let’s understand key things.
What is a lambda expression?
Lambda expression is used to implement functional interfaces.
Why lambda expression?
It’s used to pass a piece of executable code to a method as an argument rather than implementing them in a separate method/class and call inside the function.
When lambda expression?
To distribute the processing of collections over multiple threads in parallel by effectively utilizing the multicore CPUs
In the beginning, we were told that lambda expressions implement functional interfaces. The functional interface is an interface that contains only one abstract method. But it may contain more than one default and static method.
@FunctionalInterface
annotation is used to represent a functional interface. This annotation is not mandatory, but it helps the compiler to throw errors if the interface is not a functional interface at compile time.
Inside the java.util.function
package, functional interfaces are defined.
The java.util.function
package contains more than 40 functional interfaces and they are organized into 4 categories. They are
Supplier<T> {...}
Consumer<T> {...}
Predicate<T> {...}
Function<T, R> {...}
Explaining the functional interfaces is not in the scope of this article. But I’ll give a brief overview of functional interfaces to recap.
Supplier<T>
is used to get a result of typeT
. It contains an abstract methodT get()
.Consumer<T>
processes the argument typeT
and doesn’t return anything. It contains an abstract method voidaccept(T t)
.Predicate<T>
negates the argument typeT
and returns the typeboolean
. It contains an abstract methodboolean test(T t)
.Function<T, R>
computes the argument typeT
and returns the typeR
. It contains an abstract methodR apply(T t)
.
Now we have the basic knowledge of functional interfaces. Let’s implement these functional interfaces using a lambda expression.
Implementing Supplier Interface
We know that the Supplier interface contains only one abstract method get()
which doesn’t take any arguments but returns a type of T.
So the lambda expression will look like this
Supplier<Double> randomValue = () -> Math.random();System.out.println(randomValue.get());
Implementing Consumer Interface
As we know Consumer interface contains only one abstract method accept()
which takes a parameter of type T and doesn’t return anything.
So the lambda expression will look like this
Consumer<String> printString = s -> System.out::println;printString.accept("Hello World");
Implementing Predicate Interface
The Predicate interface contains only one abstract method test()
which takes an argument of type T and returns boolean.
So the lambda expression will look like this
Predicate<Integer> isGreaterThanZero = i -> (i >0) ;System.out.println(isGreaterThanZero.test(20));
Implementing Function Interface
The Function interface contains only one abstract method apply()
which takes a parameter of type T and returns a type R.
So the lambda expression will look like this
Function<String,Integer> length = s -> s.length();System.out.println(length.apply(“Hello World”));
Wrap UP
- Lambda expressions implement functional interfaces.
- Functional interfaces should have one abstract method and any number of static, default, and private methods.