Lambda Expressions in Java
In the previous blog we have learned about the Interface in Java -Part 2. If you want to know more about it, then visit the blog Interface in Java Part 2. In this blog, we will go through the concept of Lambda Expressions. Lambda Expressions were introduced in Java 8. Lambda Expression is a block of code that takes in the parameter and gives value in return. They are the same as methods but do not require a name and can be implemented right in the body of a method. We will go through the concepts in Lambda Expressions:
Lambda Expressions in Java
In the previous blog, in the section Callback using Interfaces in Java we have seen how to do work in a time interval.
e.g.
If we want to execute the code multiple times, we can create an object of the TimerDisplay class and then that object can be given to the Timer object. The actionPerformed() method defined in the class TimerDisplay contains the code that we want to execute later. Suppose we want to sort the string by length rather than directory order, in this case, we can create an object of Comparator to the sort() method.
e.g.
The compare() method is not called immediate. Rather the sort() method calls the compare() method and rearranges the elements if they are not in the correct order until the array is sorted. In both examples, there is one common thing: The block of code passed to any of them i.e. timer or sort() method. That particular block of code gets called after some time. Until now providing a particular block of code to someone was not an easy job in Java. We cannot just pass the block of code around. As Java is an object oriented language you have to create an object belonging to a particular class that has a method with the desired code. In other languages, it is possible to work with block of code directly. We know that the biggest strength of Java is its consistency and simplicity, but if we each and every feature it will become an unmaintainable mess.
Syntax of Lambda Expression
We will take the same example which we saw in the previous section. We can pass the code to check whether one string is shorter than the other. We can perform it using the following:
e.g.
In the above statement firstStr and secondStr are two strings. We must specify them as strings.
e.g.
The above expression is a lambda expression. Such an expression is simply a block of code along with the specification of any variable that can be passed to a code. If the code doesn’t fit in the single expression then we can write it just like the method enclosed with the curly braces() along with the return statement.
e.g.
If the lambda expression does not have any parameter we can provide empty parentheses just like with the no parameter method.
e.g.
If the parameter types of a lambda expression is inferred, then we can omit them.
e.g.
The compiler can omit the firstStr in the preceding statement, and the secondStr must be a string because the lambda expression is assigned to the string comparator. If a method has a single parameter with inferred type, we can even omit the parentheses
e.g.
e.g.
Output
Functional Interfaces in Java 8
There are many existing Interfaces in Java that encapsulates the block of code such as ActionListner or Comparator. Lambdas are compatible with these interfaces. Whenever an object of an interface with a single abstract method is expected then we can provide a lambda expression. This is called a functional interface. Let's consider an example of Array.sort method. In Array.sort method the second parameter requires an object of Comparator, an interface with a single method.
e.g.
The java.util.function package defines various general functional interfaces defined by the Java API. One of them is BiFunction <T,U,R> which describes the function with parameter type T and U and R return type. We can then save the string comparison lambda in a variable of that type.
e.g.
The useful interface in the package java.util.function is Predicate
e.g.
The Array class has a particular method which has the parameter as Predicate i.e.removeIf(). It is designed to pass lambda expression.
In the above statement it removes all the null values from an array. Another helpful functional interface is Supplier<T>
e.g.
Supplier interface doesn’t have any arguments. Supplier interface is used for lazy evaluation.
Method References in Java
Lambda Expressions can involve a single method. Suppose we want to print the object whenever the timer event takes place.
e.g.
Rather than passing the event object in the println() method we can just pass the println() method to the Timer constructor.
e.g.
In the above statement System.out::println is a method reference. Another example is if we want to sort a string without the concern of letters, then we can write as:
e.g.
In the above example the:: operator is used as a separator which separates the method name from the name of an object or class. There are three forms of method references:
- object::instanceMethod
- Class::instanceMethod
- Class::staticMethod
In the first form i.e object::instanceMethod, the method reference is similar to a lambda expression in which parameters are passed to the method. Let’s take the example System.out.println, in this the object is System.out, and println() is the method which is similar to the expression:
e.g.
In the second form i.e. Class::instanceMethod the first parameter will act as the implicit parameter of that method. Suppose consider the example String::compareToIgnoreCase is equivalent to :
e.g.
In the third form i.e. Class::staticMethod all the parameters are passed to the static method: Math::max(a,b) is similar to :
e.g.
In the method reference we can also use this parameter i.e. this::equals. this::equals is equivalent to
e.g.
We can also use super in method reference as follo2ws:
e.g.
The above expression uses this as the target and invokes the superclass of the given method.