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

You use the second form when the body of the lambda expression contains one or multiple statements. Note that you have to use curly braces surrounding the body of the lambda expression: (parameters) -> { statements;}

Generally, one can omit the type declarations from the lambda parameters if they can be inferred. In addition, one can omit the parentheses if there is a single parameter.

Where to Use Lambda Expressions

Now that you know how to write lambda expressions, the next question to consider is how and where to use them. In a nutshell, you can use a lambda expression in the context of a functional interface. A functional interface is one with a single abstract method. Take, for example, the two lambda expressions from the preceding code: Runnable r = () -> System.out.println("Hi"); FileFilter isXml = (File f) -> f.getName().endsWith(".xml");

Runnable is a functional interface because it defines a single abstract method called run. It turns out FileFilter is also a functional interface because it defines a single abstract method, called accept: @FunctionalInterface public interface Runnable { void run(); } @FunctionalInterface public interface FileFilter { boolean accept(File pathname); }

The important point here is that lambda expressions let you create an instance of a functional interface. The body of the lambda expression provides the implementation for the single abstract method of the functional interface. As a result, the following uses of Runnable via anonymous classes and lambda expressions will produce the same output: Runnable r1 = new Runnable() { public void run() { System.out.println("Hi!"); } }; r1.run(); Runnable r2 = () -> System.out.println("Hi!"); r2.run();

Note

You’ll often see the annotation @FunctionalInterface on interfaces. It’s similar to using the @Override annotation to indicate that a method is overridden. Here, the @FunctionalInterface annotation is used for documentation to indicate that the interface is intended to be a functional interface. The compiler will also report an error if the interface annotated doesn’t match the definition of a functional interface.

You’ll find several new functional interfaces such as Function and Supplier in the package java.util.function, which you can use for various forms of lambda expressions.

Method References

Method references let you reuse existing method definitions and pass them around just like lambda expressions. They are useful in certain cases to write code that can feel more natural and readable compared to lambda expressions. For example, you can find hidden files using a lambda expression as follows: File[] hiddenFiles = mainDirectory.listFiles(f -> f.isHidden());

Using a method reference, you can directly refer to the method isHidden using the double colon syntax (::). File[] hiddenFiles = mainDirectory.listFiles(File::isHidden);

The most simple way to think of a method reference is as a shorthand notation for lambda expressions calling for a specific method. There are four main kinds of method references:

A method reference to a static method: Function converter = Integer::parseInt; Integer number = converter.apply("10");

A method reference to an instance method. Specifically, you’re referring to a method of an object that will be supplied as the first parameter of the lambda: Function invoiceToId = Invoice::getId;

A method reference to an instance method of an existing object: Consumer print = System.out::println;

Specifically, this kind of method reference is very useful when you want to refer to a private helper method and inject it into another method: File[] hidden = mainDirectory.listFiles(this::isXML); private boolean isXML(File f) { return f.getName.endsWith(".xml"); }

A constructor reference: Supplier> listOfString = List::new;

Putting It All Together

At the start of this chapter, you saw this verbose example of Java code for sorting invoices: Collections.sort(invoices, new Comparator() { public int compare(Invoice inv1, Invoice inv2) { return Double.compare(inv2.getAmount(), inv1.getAmount()); } });

Now you’ll see exactly how to use the Java 8 features you’ve learned so far to refactor this code so it’s more readable and concise.

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