Ever since I heard Java 8 is going to support lambda expressions (aka closures), I was very enthusiastic to spice my code with such a decent and concise functional element. Most developers extensively use Anonymous Inner Classes for event handlers, comparators, basic thread/runnable implementations, etc and overburden the logic with unnecessary scaffoldings even a very simple piece of code seems complex and unwieldy. Java 8 now added Lambda expressions as part of language syntax that help solve similar problem in a very elegant manner.
It enable developers to encapsulate a single unit of behavior and pass it to other code. It’s like syntactic sugar for an anonymous class (with one method whose type is inferred) and is an object-less method. I prefer avoiding extensive theoretical material in this post, but before moving further towards understanding the syntax, structure and examples of lambdas, there is an important concept need attention.
A Functional Interface (aka Single Abstract Method type or SMA) is any
interface that contains only one abstract method. But it may contain some static
or/and default methods. java.lang.Runnable
is
an example of a Functional Interface, as it have only one run()
method, which is abstract. Similarly ActionListener interface is also a
functional interface. Following is an example of user defined functional
interface.
1
2
3
4 |
interface
Worker() { boolean
doWork(); }; |
Have a look at another templatized functional interface example:
1
2
3
4 |
interface
Operator { TYPE operate(TYPE operand1, TYPE operand2); } |
That’s it, as it’s a normal interface that just have one abstract method.
Although there is more to talk on functional interface specially java 8′s
provided packagejava.util.function
and
@FunctionalInterface
annotation but for now just focus on lambdas.
I will cover these topic in detail in a separate post.
Lambda expressions, also known as closures, are anonymous methods that provide developers with a simple and compact means for representing behavior as data.
- Brian Goetz, Specification Lead for JSR 335
To easily understand the syntax of a lambda expression we first take a look at conventional Anonymous Inner Class.
1
2
3
4
5
6
7 |
new Runnable() { public
void run() { performWork(); } }; |
Lambda expressions provide the remedy for clumsiness of an Anonymous Inner Class and convert above five lines into a single line like.
1 |
() -> performWork(); |
So, standard syntax of lambda is as follows:
1 |
() -> some expression |
Or
1 |
(arguments) -> { body just like function } |
A lambda expression consists of the following three parts:
1
2
3
4
5 |
// Taking two integers and retuning their sum ( int
x, int
y) -> x + y // lambda expression with single integer argument that returns its next integer value ( int
x) -> { return
x + 1 ; } |
You can omit the datatype of the parameters in a lambda expression.
1
2
3
4 |
// same lambdas without argument types (x, y) -> x + y (x) -> { return
x + 1 ; } |
In addition, you can omit the parentheses if there is only one parameter.
1
2 |
// single argument lambda without parentheses x -> { return
x + 1 ; } |
->
1
2
3
4
5 |
//Lambda taking no argument and returning a constant integer vale, 92 () -> 92 // taking a string as an argument and printing that on console (String s) -> { System.out.println(s); } |
1
2
3
4
5 |
// for single statement body, no need to use braces and the return statement x -> x + 1 // simple lambda with void return type () -> System.out.println(“Hello World!”) |
In the block form, the body is evaluated like a method body and a return statement returns control to the caller of the anonymous method.
Ok, we spend enough on syntax of lambda, let’s move to some real examples
To easily understand the lambda expressions, let’s start with some basic
comparative examples with anonymous inner class. In the first example, we will
see the use of lambda Comparator
interface implementation. Assume
we have a Person
class with name property, and we constructed an
array of Person
objects, named persons.
1
2
3
4
5
6
7
8
9
10
11 |
Arrays.sort(persons, new
Comparator() { @Override public
int compare(Person first, Person second) { return
first.getName().compareTo(second.getName()); } }); // it’s a standard sort but interestingly rather than passing Comparator object, it’s taking a lambda expression Arrays.sort(persons,(first, second) -> first.getName().compareTo(second.getName())); |
Notice that five lines of code turned into a single line, that’s the beauty
of lambda over anonymous inner classes. Now let’s look at another example of
Runnable
implementation. And same is in the Runnable
case.
1
2
3
4
5
6
7
8
9
10
11
12
13
14 |
Runnable printer = new
Runnable() { @Override public
void run() { System.out.println( "Hello, I’m inside runnable class..." ); } }; printer.run(); printer = () -> System.out.println( "Hello, I’m inside runnable lambda..." ); printer.run(); |
Writing lambda expression for user defined functional interface is also very
simple and easy. Following example uses Operator
custom interface
and stores lambda expression in a reference variable for the sake of
reusability;
1
2
3 |
Operator addition = (op1, op2) -> op1 + op2; System.out.println( "Addition result: "
+ addition.operate( 2 , 3 )); |
For further understanding, there is another example of lambda expressions with statement block.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 |
interface
GenericOperator { TYPE operate(TYPE ... operands); } //lambda expression with statement block GenericOperator multiply = numbers -> { int
result = 0 ; for ( int
num : numbers) result *= num; return
result; }; System.out.println( "Multiplication result: "
+ multiply.operate( 2 , 3 , 4 )); |
As demonstrated above, the block is just like a normal function block and lambdas are functional elements similar to methods, but with higher significance.
Lambdas are not actually the replacement of anonymous inner classes but a batter way to implement the single abstract method types. Both of them has their significance and are intended to use in their specific scenarios.
this
keyword to their own object,
though lambda resolves it to enclosing class where it’s written. To access
variables inside lambda from enclosing class, you can use
this
.Serializable
. Whereas its
serialization is highly discouraged like anonymous classes.invokedynamic
is used to bind methods dynamically,
that were introduced in java 7.An IntelliJ project containing the source files for the examples covered in the post.
source: http://zishanbilal.com/2014/05/08/java-8-lambda-expressions-examples/
Java 8 Lambda Expressions by Examples,布布扣,bubuko.com
Java 8 Lambda Expressions by Examples
原文:http://www.cnblogs.com/glenblogs/p/3721515.html