Java 8 – Lambda Expressions

A lambda expression is basically just a block of code that you can pass around to be executed later – once, or multiple times. Many other languages support them, so you’ve probably already used them if you’ve coded in a language other than C/C++/Java/C# (they’re also often referred to as ‘Closures’, ‘Anonymous Functions’, or ‘Blocks’).

 

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.

猜你喜欢

转载自dearls.iteye.com/blog/2252921
今日推荐