Lambda Expressions in Java 8

来源:互联网 发布:nginx过滤静态资源 编辑:程序博客网 时间:2024/05/19 02:28

1 Lambda Expressions

A lambda expression is a block of code that you can pass around so it can be executed later, once or multiple times.
The point of using lambdas is deferred execution.
There are many reasons for executing code later, such as:

  • Running the code in a separate thread
  • Running the code multiple times
  • Running the code at the right point in an algorithm
  • Running the code when something happens
  • Running the code only when necessary

It is best to think of a lambda expression as a function.
So,the syntax of lambda is very simple: parameters list, the -> arrow, and an expression body.

(String first, String second) ->{    if (first.length() < second.length())         return -1;    else if (first.length() > second.length())         return 1;    else         return 0;}

If the expression body has just one line, {} could be omitted

(String first, String second) -> first.length() - second.length()

If the parameter types can be inferred, you can omit them too

Comparator<String> comp = (first, second) -> first.length() - second.length();

The result type of a lambda expression is always inferred from context.

// context where a result of type int is expected(String first, String second) -> first.length() - second.length()

2 How to use lambdas in Java 8?

You can supply a lambda expression whenever an object of an functional interface .
A functional interface is a interface constrained to declaring only one single abstract method.

注1 :Java 8 之前接口中的方法都是抽象的,但是 Java 8 之后,接口可以定义 default 标识的“默认方法”,这些方法在接口中已有实现。

注2 :说只能声明一个抽象方法是不太准确的,还可以声明 Object 类的方法,如 boolean equals(Object obj);

注3 : Java 8 之后,提供了注解 @FunctionalInterface 来声明某个接口符合 functional interface 约束。

For example , the Arrays class has declared a method for sorting data.

public static <T> void sort(T[] a, Comparator<? super T> c)

Lets see the definition of the Comparator in the source code

@FunctionalInterfacepublic interface Comparator<T> {    int compare(T o1, T o2);    // other methods ...}

In Java, conversion to a functional interface is the only thing that you can do with a lambda expression

String[] planets = new String[] { "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus","Neptune" };   System.out.println(Arrays.toString(planets));System.out.println("Sorted by length:");Arrays.sort(planets, (first, second) -> first.length() - second.length());System.out.println(Arrays.toString(planets));

The Java API (since 8) defines a number of very generic functional interfaces in the java.util.function package.

Functional Interface Parameter Types Return Type Method name Description Runnable run Runs an action without arguments or return value Supplier T get Supplies a value of type T Consumer T accept Consumes a value of type T Function T R apply A function with argument of type T BiConsumer T, U accept Consumes values of types T and U BiFunction T, U R apply A function with arguments of type T and U Predicate T boolean test A boolean-valued function BiPredicate T, U boolean test A boolean-valued function with two args UnaryOperator T T apply A unary operator on the type BinaryOperator T, T T apply A binary operator on the type T

For primitive types, the API provides 34 available functional interfaces specializations for int, long, and double.
For example, the IntConsumer interface with an accept method requiring an int parameter.
you can define a method like this:

public static void repeat(int n, IntConsumer action){    for (int i = 0; i < n; i++) action.accept(i);}

then you can invoke this method using lambda expression like this

repeat(10, i -> System.out.println("Countdown: " + (9 - i)));

3 Variable Scope

A lambda expression has three ingredients:

  1. A block of code
  2. Parameters
  3. Values for the free variables, the variables that are not parameters and not defined inside the code block.

The technical term for a block of code together with the values of the free variables is a closure.

A lambda expression can capture the value of a variable in the enclosing scope.
The body of a lambda expression has the same scope as a nested block.

For example, the lambda expression want to be able to access variables from an enclosing method.

public static void repeatMessage(String text, int delay){    ActionListener listener = event ->    {        System.out.println(text);//text is a value of a free variable        Toolkit.getDefaultToolkit().beep();    };    new Timer(delay, listener).start();}

In Java, to ensure that the captured value is well-defned, there is an important restriction.
The rule is that any captured variable in a lambda expression must be effectively final.
An effectively final variable is a variable that is never assigned a new value after it has been initialized.

原创粉丝点击