The essay (02) _ Lambda expression of JDK 8 is further explored.

Source: Internet
Author: User

The essay (02) _ Lambda expression of JDK 8 is further explored.
Use of Lambda expressions

Nima, bad news. The project actually uses Angular js. I will clean it, and all domestic documents will go over the wall...
It seems that the Learning mode needs to be enabled...
Let's continue with Lambda.

Use generic

You can also get back the previous link example.

interface CheckPerson {    boolean test(Person p);}

We made some changes:

interface Predicate<T> {    boolean test(T t);}

The accepted domain model is Person, and the modified domain model is T, which can be dynamically bound to any domain model.
If we specify the domain model as Person, this interface is actually the following:

interface Predicate<Person> {    boolean test(Person t);}

The implemented class can be written as follows:

public class PredicateImp implements Predicate<Person>{    @Override    public boolean test(Person t) {        return false;    }}

We can specify a domain model as needed to expand the domain model.

Let's take a look at the previous example.

public static void printPersonsWithPredicate(    List<Person> roster, Predicate<Person> tester) {    for (Person p : roster) {        if (tester.test(p)) {            p.printPerson();        }    }}

This defined method is printPersonsWithPredicate. We can still use the Lambda expression when calling it:

printPersonsWithPredicate(    roster,    p -> p.getGender() == Person.Sex.MALE        && p.getAge() >= 18        && p.getAge() <= 25);

. In addition, if it is not the class of Person, it can be dynamically specified in the Lambda expression.

Vertical penetration and optimization of Lambda expressions

The above uses generics to expand the domain model, but there is still a problem in the example.

public static void printPersonsWithPredicate(    List<Person> roster, Predicate<Person> tester) {    for (Person p : roster) {        if (tester.test(p)) {            p.printPerson();        }    }}

Take a closer look at the above Code, our tester. the method test (Person p) is implemented by pulling the Lambda expression to the place where the method is called, but the printPersonsWithPredicate method also calls a p. the printPerson () method, that is, if we adjust the printPerson of Person, it will inevitably affect the logic and implementation of the printPersonsWithPredicate method. One of the most important purposes of using Lambda expressions is to extract the logic of the unique method in a functional interface so that it can be easily reflected in the called place, instead of affecting the logic of calling methods, a godlike decoupling operation is performed on the programming layer of the Code. Therefore, the above p. printPerson () does not get "decoupling", and there is another possibility of Optimization Using Lambda expressions.
We all know that conservation of energy and the transformation of time space, everything has its own nature and internal interconnection, and we save time space and will inevitably rise, and vice versa. The solution to the above problem is to use space for flexibility.
Consider the following mode:
First, we define an interface:

interface Consumer<T> {    void accept(T t);}

OK. This is a functional interface. For more information about function interfaces, see the previous article: Lambda initial experience.
Of course, we don't need to define this interface, java's latest java. util. the function package has defined such a function interface that can be used directly for us. Let's take a look at the Code:

First, understand Consumer in java. util. function <T>
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.package java.util.function;import java.util.Objects;/** * Represents an operation that accepts a single input argument and returns no * result. Unlike most other functional interfaces, {@code Consumer} is expected * to operate via side-effects. * * <p>This is a <a href="package-summary.html">functional interface</a> * whose functional method is {@link #accept(Object)}. * * @param <T> the type of the input to the operation * * @since 1.8 */@FunctionalInterfacepublic interface Consumer<T> {    /**     * Performs this operation on the given argument.     *     * @param t the input argument     */    void accept(T t);    /**     * Returns a composed {@code Consumer} that performs, in sequence, this     * operation followed by the {@code after} operation. If performing either     * operation throws an exception, it is relayed to the caller of the     * composed operation.  If performing this operation throws an exception,     * the {@code after} operation will not be performed.     *     * @param after the operation to perform after this operation     * @return a composed {@code Consumer} that performs in sequence this     * operation followed by the {@code after} operation     * @throws NullPointerException if {@code after} is null     */    default Consumer<T> andThen(Consumer<? super T> after) {        Objects.requireNonNull(after);        return (T t) -> { accept(t); after.accept(t); };    }}

This is a functional interface that satisfies the requirements of a abstract method and a static or default method.
In this interface, void accept (T t) is the method we can use to implement logic.
The default method in this interface is used by all implement methods of this interface .... Well .. What should I do here? Inherit? Well, it can be said that a class inherits an interface method, which was also a void error in the past.
All the classes that implement this interface can have this addThen method by default. The purpose of this method is to continue to use a T to complete a post-processing execution after the accept method is completed.
For example, in this scenario, we want to execute p. printPerson () and then execute p. printPerson2 () is called post-processing.
Assume that the method in Person is:

    public void printPerson() {        System.out.println(1);        // ...    }    public void printPerson2() {        System.out.println(2);        // ...    }

Call:

Consumer <Person> impl = (Person p)-> p. printPerson (); // line 1 impl. andThen (Person p)-> p. printPerson2 (); // Line 2

In line 1 of the Code above, Lambda expressions are used to define the implementation of the accept method in Consumer.
In line 2, Lambda expressions are used directly in the andThen parameter (also a Consumer Interface) to define the post-processing execution subject Person and the printPerson2 () method that it calls.
What will the above two lines of code look like after execution?
The answer is, there is no input.
Because we only define an impl, it implements the Lambda definition of the accept method and the Lambda definition of its andThen post-processing, but it is not called, so if you want to call it, it should be:

Consumer <Person> impl = (Person p)-> p. printPerson (); // line 1 impl. andThen (Person p)-> p. printPerson2 (); // line 2 impl. accept (new Person (); // Row 3

After adding Row 3, you can press "1 2" on the console.

Chain application of Consumer <T>

From the Consumer code, we can see that every time the default method returns a Consumer implementation, we can actually implement the infinite andThen?
Suppose we have printPerson1 ~ in Person ~ If we need to use Lambda expressions to write these 10 methods into a Consumer implementation class, How to do?
See:

Consumer <Person> impl = (Consumer <Person>) (Person p)-> p. printPerson () // Line 1. andThen (Person p)-> p. printPerson2 () // Line 2. andThen (Person p)-> p. printPerson3 ())//.... andThen (Person p)-> p. printPerson4 ()). andThen (Person p)-> p. printPerson5 ()). andThen (Person p)-> p. printPerson6 ()). andThen (Person p)-> p. printPerson7 ()). andThen (Person p)-> p. printPerson8 ()). andThen (Person p)-> p. printPerson9 ()). andThen (Person p)-> p. printPerson10 (); impl. accept (new Person ());

Code parsing:
First, Row 1 defines the most basic accept method, and then appends nine andThen methods after row 2. Each andThen implements a p. for the injection of the printPersonx () method, the impl is 10 p. printPersonx. Amazing and abnormal. The simple expansion of Lambda expressions makes it easy and clear to call a complicated anonymous internal class.

Return to our example and use Consumer for Optimization
public static void printPersonsWithPredicate(    List<Person> roster, Predicate<Person> tester) {    for (Person p : roster) {        if (tester.test(p)) {            p.printPerson();        }    }}

After using Consumer, our method definition should be:

Public static void processPersons (List <Person> roster, Predicate <Person> tester, Consumer <Person> block) {// Row 1 for (Person p: roster) {if (tester. test (p) {block. accept (p); // Row 2 }}}

Row 1: A Consumer parameter block is added to the method.
Row 2: Call the accept method in the interface
Suppose we use a class to implement the Consumer interface, it should be the following sauce:

public class ConsumerImp implements Consumer<Person> {    @Override    public void accept(Person t) {        t.printPerson();    }}

If you call the processPersons method, we can specify the ConsumerImp instance as the 3rd parameter.
OK. If you use a Lambda expression to call the processPersons method:

ProcessPersons (roster, // row 0 p-> p. getGender () = Person. sex. MALE // Row 1 & p. getAge ()> = 18 // Row 2 & p. getAge () <= 25, // Row 3 p-> p. printPerson () // Line 4 );

Three parameters.
Row 0: the first parameter.
Line 1 ~ Row 3: Use Lambda to write a functional interface expression that implements Predicatede.
Row 4: Expression of the Consumer function interface method written by Lambda.
That is to say, the printPerson () method originally implemented using the accept method in ConsumerImp simplifies this implementation class using Lambda expressions and saves the di process of the implementation class.
It seems a lot easier to implement, but it may be a bit Easy at the beginning.

There are already too many other...

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.