Behaviour Parameterisation…pattern which allows you to write such a flexible code which can cope up with any requirement change.
Now you may wondering why I am talking about this weird sounding pattern instead lambda expression, right?
Well, let me tell you that we will soon get to know about lambda expression in detail but understanding Behaviour Parameterization pattern will definitely help you thoroughly how lambda expression is useful to write concise and succinct code and you will start feeling power of lambda expression which is one of prime feature of java 8 release.
Lets say, we have list of Books and you need to find Books with greater than 200 pages. You could write a method getBooksGreaterThanPages():
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public List<Book> getBooksGreaterThanPages(List<Book> allBooks, int minPages){ | |
List<Book> books = new ArrayList<>(); | |
for (Book book : allBooks){ | |
if(book.getPages() > minPages) | |
books.add(book); | |
} | |
return books; | |
} |
You end up with writing and endlessly adding new methods getBooks*() which dealt with corresponding property of Book based on changing requirement.
To solve this problem what we need is such conditional behaviour which filters the data and such a behaviour can be passed as parameter to method or function.
This is Behaviour Parameterization.
Let me clear you by example,
Lets represent the Conditional behaviour abstraction by defining BookPredicate interface and use it.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface BookPredicate{ | |
boolean acceptBook(Book book); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
List<Book> getBooks(List<Book> allBooks, BookPredicate bookPredicate) { | |
List<Book> books = new ArrayList(); | |
for (Book book : allBooks) { | |
if (bookPredicate.acceptBook(book)) | |
books.add(book); | |
} | |
return books; | |
} |
Lets say we wanted books from Diamond publications and price below $50 and pages less than 1000 then:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
List<Book> books = getBooks(allBooks, new BookPredicate() { | |
@Override | |
public boolean acceptBook(Book book) { | |
return book.getPublicationsName().equals("Diamond") | |
&& book.getPrice() <= 50 | |
&& book.getPages() < 1000; | |
} | |
}); |
Though, we have achieved flexibility but loose the readability somewhere.
Ideally, what we want is flexibility of code plus conciseness, thats where lambda expression comes into picture.
Using lambda expression we can concisely write previous code snippet like this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
List<Book> books = getBooks(allBooks, | |
book -> book.getPublicationsName().equals("Diamond") | |
&& book.getPrice() <= 50 | |
&& book.getPages() < 1000); |
Lambda expression definition:
In the simple terms, lambda expression is anonymous function that can be passed around to method as a parameter, can stored in variable and also can returned a result.
Anonymous because it does not have a declared name
Function because its more like function equipped with list of parameters, expression body and return value etc.
Lambda expression syntax:
Read some more examples of lambda expression:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Runnable r = () -> System.out.println("Hello Runnable”); | |
Comparator c = (Book b1, Book b2) -> Double.compare(b1.getPrice(), b2.getPrice()); | |
BookPredicate b = b -> b.getPrice() > 50; |
1. Parameter List e.g. (Book b1, Book b2), if no parameters then empty parentheses.
2. Arrow compose of two - and > character
3. Body e.g. Double.compare(b1.getPrice(), b2.getPrice())
When body of lambda expression consist of multiple statement then encapsulate the body with {} brackets, like this:
(parameters) -> {
statements1;
statements2;
}
One can omit the () parentheses if single parameter is present.
e.g. b -> b.getPrice() < 50 //see parameter b is without () parenthesis
One can omit the {} brackets if single statement is present.
You can omit return keyword if single return statement present. e.g. Double.compare(b1.getPrice(), b2.getPrice()) //here we skipped return keyword.
Where to use lambda expression:
You can use lambda expression in context of functional interface.
Functional interface are interface with single abstract method.
e.g. Runnable is functional interface, since it has only one run() abstract method defined.
Functional interface is annotated with @FunctionalInterface e.g.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@FunctionalInterface | |
public interface Runnable{ | |
void run(); | |
} |
body of lambda expression is implementation of single abstract method hence
following Runnable with anonymous class and lambda expression generates same output:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//functional interface implementation with anonymous class | |
Runnable r1 = new Runnable() { | |
public void run() { | |
System.out.println("Hello"); | |
} | |
}; | |
r1.run(); | |
//functional interface implementation with Lambda expression | |
Runnable r2 = () -> System.out.println("Hello"); | |
r2.run(); |
Comments
Post a Comment