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.
- Refer Lambda expression as method parameter to know more about how lambda expression can be passed as a method parameter.
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
You may also like-
No comments:
Post a Comment