As we have already seen in the post about Java lambda expressions, they implement the abstract method of the functional interface. In that way lambda expressions can provide a compact and easy to read code which is not repetitive by using them in place of anonymous classes.
Using functional interfaces with anonymous inner classes is a common pattern in Java, from Java 8 lambda expressions provide a better alternative by implementing the abstract method of the functional interface.
In this post we'll see some examples of lambda expressions in Java like Runnable as lambda expression,
Comparator as lambda expression, lambda expression implementation of Predicate functional interface.
Runnable as Lambda expression example
It is very common to implement the run()
method of Runnable
interface as an anonymous class, now same
can be done with lambda expression in fewer lines increasing readability.
public class RunnableLambda {
public static void main(String[] args) {
// Runnable using anonymous class
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Runnable with anonymous");
}
}).start();
// Runnable using lambda
new Thread(()->System.out.println("Runnable Lambda")).start();
}
}
It can be seen how concise the implementation becomes with
lambda expression.
Comparator as Lambda expression example
In this example we'll have a list of Person object and they are sorted on first name using Comparator.
Person class
public class Person {
private String firstName;
private String lastName;
private int age;
private char gender;
Person(String firstName, String lastName, int age, char gender){
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.gender = gender;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
public char getGender() {
return gender;
}
public String toString(){
StringBuffer sb = new StringBuffer();
sb.append(getFirstName()).append(" ");
sb.append(getLastName()).append(" ");
sb.append(getAge()).append(" ");
sb.append(getGender());
return sb.toString();
}
}
// Functional interface
@FunctionalInterface
interface IMyInterface {
Person getRef(String firstName, String lastName, int age, char gender);
}
public class LambdaExpressionDemo {
public static void main(String[] args) {
List<Person> personList = createList();
// comparator implementation as anonymous class
// and sorting the list element on the basis of first name
Collections.sort(personList, new Comparator<Person>() {
public int compare(Person a, Person b) {
return a.getFirstName().compareTo(b.getFirstName());
}
});
System.out.println("Sorted list with anonymous implementation");
for(Person p : personList){
System.out.print(p.getFirstName() + " ");
}
// creating the same list again to use with lambda expression
personList = createList();
// Providing the comparator functional interface compare
/// method as lambda exression
Collections.sort(personList, (Person a, Person b) ->
a.getFirstName().compareTo(b.getFirstName()));
System.out.println("Sorted list with lambda implementation");
// Using the new ForEach loop of Java 8
// used with lambda expression
personList.forEach((per) -> System.out.print(per.getFirstName() + " "));
}
// Utitlity method to create list
private static List<Person> createList(){
List<Person> tempList = new ArrayList<Person>();
IMyInterface createObj = Person::new;
Person person = createObj.getRef("Ram","Tiwari", 50, 'M');
tempList.add(person);
person = createObj.getRef("Prem", "Chopra", 13, 'M');
tempList.add(person);
person = createObj.getRef("Tanuja", "Trivedi", 30, 'F');
tempList.add(person);
person = createObj.getRef("Manoj", "Sharma", 40, 'M');
tempList.add(person);
System.out.println("List elements are - ");
System.out.println(tempList);
return tempList;
}
}
Output
List elements are -
[Ram Tiwari 50 M, Prem Chopra 13 M, Tanuja Trivedi 30 F, Manoj Sharma 40 M]
Sorted list with anonymous implementation
Manoj Prem Ram Tanuja List elements are -
[Ram Tiwari 50 M, Prem Chopra 13 M, Tanuja Trivedi 30 F, Manoj Sharma 40 M]
Sorted list with lambda implementation
Manoj Prem Ram Tanuja
Here I have used some of the features of Java 8 like Constructor reference using
Double colon operator,
which is this line IMyInterface createObj = Person::new
;
Also used the new
forEach statement in Java 8 with lambda expression, which is this line-
personList.forEach((per) -> System.out.print(per.getFirstName() + " "));
Same way lambda expression can be used with other functional interfaces like Callable, ActionListener etc.
Lambda expression with inbuilt functional interfaces
With Java 8 many new functional interfaces are being defined, in fact there is a whole new package
java.util.function
added with many functional interfaces. The interfaces in this package are general purpose
functional interfaces used by the JDK, and are available to be used by user code as well.
The following are some of the examples of new functional interfaces in Java 8-
public interface Predicate<T> {
boolean test(T t);
}
public interface Function<T,R> {
R apply(T t);
}
public interface BinaryOperator<T> {
T apply(T left, T right);
}
public interface Consumer<T> {
void accept(T t);
}
public interface Supplier<T> {
T get();
}
Starting with Java 8 these functional interfaces can be implemented by means of lambda expressions and
method references.
We have already seen in the above examples how using lambda expressions we can solve the vertical problem
associated with anonymous classes and make the code concise and more readable. Here let's see an example using one of the inbuilt functional interface.
Predicate functional interface as Lambda expression implementation
Supposing we want to use inbuilt functional interface named Predicate declared as follows:
public interface Predicate<T> {
boolean test(T t);
}
We have a class person and using that person list we want to implement a search criteria where we want
to search and print the following-
- List of drivers (age >= 16)
- List of voters (age >= 18)
- List of senior citizens (age >= 60)
We'll use the inbuilt functional interface Predicate to set up the search criteria. Note that we don’t need to explicitly write the Predicate interface as it is already available, we just need to import it from java.util.function package.
Person Class
public class Person {
private String firstName;
private String lastName;
private int age;
private char gender;
public Person(String firstName, String lastName, int age, char gender){
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.gender = gender;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
public char getGender() {
return gender;
}
public String toString(){
StringBuffer sb = new StringBuffer();
sb.append(getFirstName()).append(" ");
sb.append(getLastName()).append(" ");
sb.append(getAge()).append(" ");
sb.append(getGender());
return sb.toString();
}
}
@FunctionalInterface
interface IMyFunc {
Person getRef(String firstName, String lastName, int age, char gender);
}
public class LambdaDemo {
public static void main(String args[]){
List<Person> personList = createList();
ListPerson listPerson = new ListPerson();
//Predicates
// For age >= 16
Predicate<Person> allDrivers = p -> p.getAge() >= 16;
// For age >= 18
Predicate<Person> allVoters = p -> p.getAge() >= 18;
// For age >= 60
Predicate<Person> allSeniorCitizens = p -> p.getAge() >= 60;
// calling method to list drivers, passing predicate as arg
listPerson.listDrivers(personList, allDrivers);
// calling method to list voters, passing predicate as arg
listPerson.listVoters(personList, allVoters);
// calling method to list senior citizens, passing predicate as arg
listPerson.listSeniorCitizens(personList, allSeniorCitizens);
}
// Utitlity method to create list
private static List<Person> createList(){
List<Person> tempList = new ArrayList<Person>();
// Constructor reference
IMyFunc createObj = Person::new;
Person person = createObj.getRef("Ram","Tiwari", 50, 'M');
tempList.add(person);
person = createObj.getRef("Prem", "Chopra", 13, 'M');
tempList.add(person);
person = createObj.getRef("Tanuja", "Trivedi", 30, 'F');
tempList.add(person);
person = createObj.getRef("Manoj", "Sharma", 40, 'M');
tempList.add(person);
person = createObj.getRef("John", "Trevor", 70, 'M');
tempList.add(person);
person = createObj.getRef("Alicia", "Sliver", 17, 'F');
tempList.add(person);
System.out.println("List elements are - ");
System.out.println(tempList);
return tempList;
}
}
class ListPerson {
// method to list drivers
public void listDrivers(List<Person> personList, Predicate<Person> pred){
List<Person> driverList = new ArrayList<Person>();
for(Person person : personList){
if (pred.test(person)){
driverList.add(person);
}
}
System.out.println("List of drivers ");
printList(driverList);
}
// method to list voters
public void listVoters(List<Person> personList, Predicate<Person> pred){
List<Person> voterList = new ArrayList<Person>();
for(Person person : personList){
if (pred.test(person)){
voterList.add(person);
}
}
System.out.println("List of voters ");
printList(voterList);
}
// method to list senior citizens
public void listSeniorCitizens(List<Person> personList, Predicate<Person> pred){
List<Person> seniorCitizenList = new ArrayList<Person>();
for(Person person : personList){
if (pred.test(person)){
seniorCitizenList.add(person);
}
}
System.out.println("List of senior citizens ");
printList(seniorCitizenList);
}
// Method used for printing the lists
private void printList(List<Person> personList){
personList.forEach((p) -> System.out.print(" FirstName - " + p.getFirstName()
+ " LastName - " + p.getLastName() + " Age - " + p.getAge()));
System.out.println("");
}
}
It can be seen how concise and readable the code becomes and it is also non-repetitive, if we were using
anonymous classes to write these search criteria we would have done the same chore of taking new instance of
interface Predicate and overriding the test method for each search criteria. The anonymous class implementation
for getting the list of drivers would have looked like this.
listPerson.listDrivers(personList, new Predicate<Person>(){
@Override
public boolean test(Person p){
return p.getAge() >=16;
}
});
So it can be seen how lambda expression can help with solving the vertical problem associated with anonymous
class and provides a better alternative to provide implementation of functional interfaces.
That's all for this topic Lambda Expression Examples in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!
Related Topics
-
Functional Interface Annotation in Java
-
Method Reference in Java
- How to Resolve Local Variable Defined in an Enclosing Scope Must be Final or Effectively Final Error
-
Java Lambda Expression And Variable Scope
-
Java Lambda Expressions Interview Questions And Answers
You may also like-
-
How HashMap Works Internally in Java
-
Executor And ExecutorService in Java With Examples
-
final Vs finally Vs finalize in Java
-
Difference Between throw And throws in Java
-
static Method Overloading or Overriding in Java
-
Covariant Return Type in Java
-
Effectively Final in Java 8
-
Interface Default Methods in Java 8