Java 8 Lambda Expressions

Your First Lambda Expression:

There is a general usage in Swing library: we need a action listener to response a user operation.
Before Java 8, we have to create a new inner class which implements ActionListener interface and overide its unique method actionPerformed like the following code:

1
2
3
4
5
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.out.println("button clicked");
}
});

There are two problem:

1. So many template codes
2. The codes are not easy to read without expressing the purpose of the programmers

With Java 8, we can create a lambda expression:

1
button.addActionListener(event -> System.out.println("button clicked"));

Instead of passing in an object that implements an interface, we are passing in a bock of code : a function without a name.
In this code, we do not need to explicitly declare the type of event. In Lambda Expression, java compiler can infer the type of variable event from the context.

Note: For the sake of readability and familiarity, you have the option to include the type declarations, and sometimes the compiler
just can’t work it out!

How to Spot a Lambda in a Haystack

The following code are five forms of lambda expressions as an example:

1
2
3
4
5
6
7
8
Runnable noArguments = () -> System.out.println("Hello World");
ActionListener oneArgument = event -> System.out.println("button clicked");
Runnable multiStatement = () -> {
System.out.print("Hello");
System.out.println(" World");
};
BinaryOperator<Long> add = (x, y) -> x + y;
BinaryOperator<Long> addExplicit = (Long x, Long y) -> x + y;

Using Values, Not Varialbes

When you want to pass a varible outside the anonymous method into the method, you should declared the variable as final. Making a variable final means that you can’t reassign to that variable.

1
2
3
4
5
6
final String name = getUserName();
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.out.println("hi " + name);
}
});

For lambda expression, although you do not need to set the outside variable as final, but you can still not change the value. If you changed, there will be an complie error.

1
2
3
4
5
6
7
interface Formula {
double calculate(int a);

default double sqrt(int a) {
return Math.sqrt(a);
}
}

Default Methods for Interfaces

Java 8 enables us to add non-abstract method implementations to interfaces by utilizing the default keyword. This feature is also known as Extension Methods. Here is our first example:

1
2
3
4
5
6
7
interface Formula {
double calculate(int a);

default double sqrt(int a) {
return Math.sqrt(a);
}
}

Functional Interfaces

A functional interface is an interface with a single abstract method that is used as the type of a lambda expression.

How does lambda expressions fit into Javas type system? Each lambda corresponds to a given type, specifibd by an interface. A so called functional interface must contain exactly one abstract method declaration. Each lambda expression of that type will be matched to this abstract method. Since default methods are not abstract you’re free to add default methods to your functional interface.

To ensure that your interface meet the requirements, you should add the @FunctionalInterface annotation. The compiler is aware of this annotation and throws a compiler error as soon as you try to add a second abstract method declaration to the interface.

Example:

1
2
3
4
@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
}

Keep in mind that the code is also valid if the @FunctionalInterface annotation would be ommited.

Interface name Arguments Returns Example
Predicate T boolean Has this album been released yet?
Consumer T void Printing out a value
Function T R Get the name from an Artist object
Supplier None T A factory method
UnaryOperator T T Logical not (!)
BinaryOperator (T, T) T Multiplying two numbers (*)