A quick example to show the syntax: sorting list of custom elements
Often you would solve this by defining an anonymous inner class that implements the Comparator interface. With Java 8, you can instead provide a lambda expression that defines the comparison:
You have a list (dateItems) of objects that have a member of type Date.
List<DatedItem> dateItems = <…get items…>
dateItems.sort( (DatedItem a, DatedItem b) -> { returna.date().compareTo(b.date() } );
Syntax
- General structure: ( arguments ) -> { body }
- A ‘left’ and ‘right’ side separated by a ‘->’ token. The left side defines the ‘incoming’ parameters. The right side defines the code to execute.
- A lambda expression can have zero, one or more parameters.
- The type of the parameters can be explicitly declared or it can be inferred from the context. e.g. (int a) is same as just (a)
- Parameters are enclosed in parentheses and separated by commas. e.g. (a, b) or (int a, int b) or (String a, int b, float c)
- Empty parentheses are used to represent an empty set of parameters. e.g. () -> 42
- When there is a single parameter, if its type is inferred, it is not mandatory to use parentheses. e.g. a -> return a*a
- The body of the lambda expressions can contain zero, one or more statements.
- If body of lambda expression has single statement curly brackets are not mandatory and the return type of the anonymous function is the same as that of the body expression.
- When there is more than one statement in body than these must be enclosed in curly brackets (a code block) and the return type of the anonymous function is the same as the type of the value returned within the code block, or void if nothing is returned.
Functional Interfaces
A ‘functional interface’ is an interface that declares a single abstract method. For example java.lang.Runnable (declares only run() method), or java.awt.event.ActionListener (declares only actionPerformed(ActionEvent) method). Wherever a functional interface is used, a lambda can be used in its place. E.g. :
newThread( () -> System.out.println("thread started") ).start();
Examples
-- Thread execution --
//Old way:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Hello from thread");
}
}).start();
//New way:
new Thread( () -> System.out.println("Hello from thread") ).start();
-- Button handling --
//Old way:
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("The button was clicked using old fashion code!");
}
});
//New way:
button.addActionListener( (e) -> { System.out.println("The button was clicked. From lambda expressions !"); });
-- List processing --
//Old way:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
for(Integer n: list) {
System.out.println(n);
}
//New way:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
list.forEach(n -> System.out.println(n));
-- Map reduce --
//Old way:
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
intsum = 0;
for(Integer n : list) {
intx = n * n;
sum = sum + x;
}
System.out.println(sum);
//New way:
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
intsum = list.stream().map(x -> x*x).reduce((x,y) -> x + y).get();
System.out.println(sum);
** Note use of new Java8 Stream APIs. (see java.util.stream.Stream).
Comparator is a functional interface?
Above we used a lambda expression instead of a Comparator in the ArrayList.sort() method. In order for this to work, Comparator must be a functional interface. When I was looking through this I got hung up on why Comparator was a functional interface since a functional interface is defined as: “More precisely, a functional interface is defined as any interface that has exactly one abstract method.” However, if you look at the Comparator interface, you’ll see that it actually has two declared methods: compare() and equals(). To clear up any confusion – the explanation is: “The interface Comparator
is functional although it explicitly declares two methods, because only one is abstract; equals
is an explicit declaration of a concrete method inherited from Object
that, without this declaration, would otherwise be implicitly declared.”
There’s more that can be said about lambda expressions (specifically about lexical scoping and how ‘this’ is handled), but this email is getting too long so consider this just a primer J.
-------------
In Java8, an anonymour inner class can access a non-final local variable, and this this applies to both anonymous inner classes and lambdas expressions. That’s because Java8 compiler does that for us automatically. That also makes lambda expressions easier to access the outer variable. However, as Jingwei mentioned, we can’t modify its value (or modify the reference of container type, but we can modify the contents in container, of course), it’s immutable.
相关推荐
This fully updated and greatly enhanced fourth edition covers the key developments introduced in Java 8, including material on JavaFX, lambda expressions and the Stream API. Topics and features: ...
Core Java Volume I–Fundamentals, 1 (11th Edition) By 作者: Cay S. Horstmann ISBN-10 书号: 0135166306 ISBN-13 书号: 9780135166307 Edition 版本: 11 出版日期: 2018-09-06 pages 页数: 928 The #1 Java ...
OCP Java SE 8 Programmer II Exam Guide (Exam 1Z0-809) By 作者: Kathy Sierra – Bert Bates – Elisabeth Robson ...Lambda expressions and functional interfaces Streams Threads Concurrency
Java 9 with JShell by Gaston C. Hillar English | 29 Mar. 2017 | ASIN: B01N388HH3 | 408 Pages | AZW3...Object-Oriented, Functional Programming, and Lambda Expressions Modularity in Java 9 Exercise Answers
- **It's All About Signatures**: Emphasizes the importance of lambda expressions' syntax and how they are used in method signatures. - **The LINQ Syntax**: Introduces the query syntax used in LINQ ...
PEP 308: Conditional Expressions PEP 309: Partial Function Application PEP 314: Metadata for Python Software Packages v1.1 PEP 328: Absolute and Relative Imports PEP 338: Executing Modules as ...