Читаем Introducing Java 8 полностью

The motivation for introducing lambda expressions into Java is related to a pattern called behavior parameterization. This pattern lets you cope with requirement changes by letting you write more flexible code. Prior to Java 8, this pattern was very verbose. Lambda expressions fix that by letting you utilize the behavior parameterization pattern in a concise way. Here’s an example: say you need to find invoices greater than a certain amount. You could create a method findInvoicesGreaterThanAmount: List findInvoicesGreaterThanAmount(List invoices, double amount) { List result = new ArrayList<>(); for(Invoice inv: invoices) { if(inv.getAmount() > amount) { result.add(inv); } } return result; }

Using this method is simple enough. However, what if you need to also find invoices smaller than a certain amount? Or worse, what if you need to find invoices from a given customer and also of a certain amount? Or, what if you need to query many different properties on the invoice? You need a way to parameterize the behavior of filter with some form of condition. Let’s represent this condition by defining InvoicePredicate interface and refactoring the method to make use of it: interface InvoicePredicate { boolean test(invoice inv); } List findInvoices(List invoices, InvoicePredicate p) { List result = new ArrayList<>(); for(Invoice inv: invoices) { if(p.test(inv)) { result.add(inv); } } return result; }

With this useful code, you can cope with any requirement changes involving any property of an Invoice object. You just need to create different InvoicePredicate objects and pass them to the findInvoices method. In other words, you have parameterized the behavior of findInvoices. Unfortunately, using this new method introduces additional verbosity, as shown here: List expensiveInvoicesFromOracle = findInvoices(invoices, new InvoicePredicate() { public test(Invoice inv) { return inv.getAmount() > 10_000 && inv.getCustomer() == Customer.ORACLE; } });

In other words, you have more flexibility but less readability. Ideally, you want both flexibility and conciseness, and that’s where lambda expressions come in. Using this feature, you can refactor the preceding code as follows: List expensiveInvoicesFromOracle = findInvoices(invoices, inv -> inv.getAmount() > 10_000 && inv.getCustomer() == Customer.ORACLE);

Lambda Expressions Defined

Now that you know why you need need lambda expressions, it’s time to learn more precisely what they are. In the simplest terms, a lambda expression is an anonymous function that can be passed around. Let’s take a look at this definition in greater detail: Anonymous

A lambda expression is anonymous because it does not have an explicit name as a method normally would. It’s sort of like an anonymous class in that it does not have a declared name. Function

A lambda is like a method in that it has a list of parameters, a body, a return type, and a possible list of exceptions that can be thrown. However, unlike a method, it’s not declared as part of a particular class. Passed around

A lambda expression can be passed as an argument to a method, stored in a variable, and also returned as a result.

Lambda Expression Syntax

Before you can write your own lambda expressions, you need to know the syntax. You have seen a couple of lambda expressions in this guide already: Runnable r = () -> System.out.println("Hi"); FileFilter isXml = (File f) -> f.getName().endsWith(".xml");

These two lambda expressions have three parts:

A list of parameters, e.g. (File f)

An arrow composed of the two characters - and >

A body, e.g. f.getName().endsWith(".xml")

There are two forms of lambda expressions. You use the first form when the body of the lambda expression is a single expression: (parameters) -> expression

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже