(3) Lambda and function--response spring's DAO spell device

Source: Internet
Author: User

This series of articles index: "Response spring's DAO spell device"
Previously summary: What is responsive programming | Responsive flow
This article source

1.3 Hello,reactive World

The first two articles introduce the characteristics of responsive programming and responsive streaming, and always talk about the concept of the end is boring, or to tap the code to actually feel the response to the programming of the "feel" bar.

In this section, let's take a look at lambda and functional (already known friends can jump directly to 1.3.2), be familiar with how to use reactor for responsive programming, and then use Spring Boot2, based on Spring 5 Webflux and reactive Spring data progressively develops a "Hello world" level of restful service.

1.3.1 Lambda and functional type

In reactive programming, the rate of lambda and function is quite high, so that friends on the Internet often use "function-responsive programming" in the introduction of "responsive programming". The similarities and differences between the two words have always been controversial, although the difference is not like "JavaScript and Java", "Lei Feng Tower and Leifeng" so big, but casual mixing or will appear very unprofessional:

    • The focus of function-responsive programming is on "functional" language features, a concept that was finalized 20 years ago.
    • Responsive programming focuses on the asynchronous programming paradigm of "event-based Flow", which drives the execution of logic by constantly generated data/time.

This series of articles deals with "responsive programming", and you'll just have to listen to it and use it with caution when it comes to "function-responsive programming." lambda expression

Why is lambda and function often used in responsive programming, when the book is back? I wonder if you still have an impression of the pseudo-code in section 1.1.3:

cartEventStream        // 分别计算商品金额        .map(cartEvent -> cartEvent.getProduct().getPrice() * cartEvent.getQuantity())        ...

cartEventStreamis a data stream in which the element is one cartEvent , and the map method is able to cartEvent "transform/Map", where we convert it to double the amount of the type.

In addition to the conversion/mapping (map), there are filtering (filter), providing (supply), consumption (consume) and so on the elements of the flow of operations logic/Policy , and logic/policy is usually defined by methods.

Before Java 8, this was a bit of a hassle. We know that Java is an object-oriented programming language, except for a few native types, everything is an object. The method used to define the logical/policy cannot exist independently and must be wrapped in an object. For example, we are more familiar with the Comparator only way to compare represent a comparison strategy, when used, it needs to be wrapped in an object to use the method of the policy. Example description (source code):

  @Testpublic void Studentcomparetest () {@Data @AllArgsConstructor class Student {//1 private int        Id        private String name;        private double height;    private double score;    } list<student> students = new arraylist<> ();    Students.add (New Student (10001, "Zhang San", 1.73, 88));    Students.add (New Student (10002, "John Doe", 1.71, 96));    Students.add (New Student (10003, "Harry", 1.85, 88)); Class Studentidcomparator<s extends student> implements comparator<s> {//2 @Override public in        T compare (s S1, s S2) {return Integer.compare (S1.getid (), S2.getid ());    }} students.sort (new studentidcomparator<> ()); SYSTEM.OUT.PRINTLN (students);}  
    1. @DataAnd @AllArgsConstructor is the annotation provided by Lombok, can generate constructs the method, Getter/setter, ToString and so on in the compiled bytecode. Dependencies are as follows:

      <dependency>    <groupId>org.projectlombok</groupId>    <artifactId>lombok</artifactId>    <version>1.16.20</version></dependency>

Note: In this section and beyond, you can query the MAVEN search library for new and appropriate versions of MAVEN dependencies.

    1. StudentIdComparatorA comparison strategy is cured in which the object is passed to the Student.id method when students it is sorted. StudentIdComparator sort The output order is as follows:

      [Student (id=10001, Name= Zhang San, height=1.73, score=88.0), Student (id=10002, name= John Doe, height=1.71, score=96.0), Student (id= 10003, Name= Harry, height=1.85, score=88.0)]

Let's say that we need to sort the students ' height or score, the definition Comparator of the implementation class is a bit cumbersome and unnecessary, and the "traditional" simplification is to pass in the anonymous inner class directly:

    students.sort(new Comparator<Student>() {        @Override        public int compare(Student s1, Student s2) {            return Double.compare(s1.getHeight(), s2.getHeight());        }    });

But in fact, we will find that no matter what kind of comparison strategy, only compare the code within the method changes, that is, the sort method is concerned about only the two parameters passed in Student s1, Student s2 and the return of the conclusion of return Double.compare(s1.getHeight(), s2.getHeight()) this comparison strategy, why not just keep them?

students.sort((Student s1, Student s2) -> {return Double.compare(s1.getHeight(), s2.getHeight());});

This looks like the code is much less. (Student s1, Student s2) -&gt; {return Double.compare(s1.getHeight(), s2.getHeight())}here is the lambda expression, the syntax for the lambda expression is as follows:

(type1 arg1, type2 arg2...) -> { body }

-&gt;The parameters and method bodies are represented before and after each. From the way code is written, this can be counted as a "functional" programming paradigm, as we pass to sort a "function" in the form of a lambda expression, which has inputs and outputs that the developer appears to be naked and not encapsulated with objects.

One of the core features of the "functional" programming Paradigm: A function is a "class citizen".
The so-called "first Class" refers to functions that are equal to other data types, can be assigned to other variables, can also be passed as arguments to another function, or as a return value for other functions.

But it is only "looks" is "functional", Java is ultimately object-oriented language, List.sort the method definition is still to accept an Comparator object as a parameter. But do you have to tangle with Java as a purely functional language? There is no need, practical first.

So, the question is, sort how do you think of this lambda "as" an Comparator object?

It is not difficult to see that Comparator an interface has only one abstract method, so it is sort not difficult to "infer" that the input parameters and method bodies defined by Lambda are exactly the only abstract method compare . Interface

Comparatoran interface like this, which has only one abstract method, is called a functional interface (functional Interface). As with Comparator similar, the only abstract method of other functional interfaces can also be represented by Lambda.

We look at Comparator the source code, found that it is a more @FunctionalInterface annotated, to indicate that it is a functional interface. The interface marked with this annotation has only one abstract method, otherwise it will report a compilation error.

Look at the other interfaces that have only one abstract method, such as Runnable and Callable , the discovery also adds annotations after Java 8 @FunctionalInterface . For runnable, the interface is defined as follows:

@FunctionalInterfacepublic interface Runnable {    public abstract void run();}

It is not difficult to speculate that its lambda should be () -&gt; { body } written, it does not receive any parameters, the method body also has no return return value, used like this:

new Thread(() -> {doSomething();});

In addition, with the addition of lambda, there is a java.util.function package that defines some of the common function-type interfaces. Like what:

    • Function, takes an input parameter and returns a result. The type of the parameter and the return value can be different, the map lambda in our previous method is the expression of this function interface;
    • Consumer, accepts an input parameter and has no returned action. For example, if we print every element of the data stream, we can use Consumer lambda based;
    • Supplier, no input parameters are required and only the results are returned. Look at the interface name to know is to play the role of the object factory;
    • Predicate, takes an input parameter and returns a Boolean result. For example, when we filter the elements in the data flow, we can use lambda based Predicate ;
    • ... Simplified Lambda

The method of using lambda as a parameter can infer the abstract method of which function interface the lambda represents. Similarly, the compilation period can be more inferred. Let's go back to the original Comparator example and continue simplifying the lambda expression as follows:

students.sort((Student s1, Student s2) -> {return Double.compare(s1.getHeight(), s2.getHeight());});

1) First, the type of the parameter passed in can be inferred. Because it students is an Student array of elements List&lt;Student&gt; , its sort methods naturally receive Comparator&lt;? super Student&gt; objects as parameters, all of which can be constrained by generics.

students.sort((s1, s2) -> {return Double.compare(s1.getHeight(), s2.getHeight());});

2) If there is only one return statement, return and the curly braces of the method body can be omitted ( compare the return value of the method is the lambda return value):

students.sort((s1, s2) -> Double.compare(s1.getHeight(), s2.getHeight()));

3) Note that the Comparator interface also provides a rich static method, such as:

public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) {    Objects.requireNonNull(keyExtractor);    return (Comparator<T> & Serializable)        (c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));}

This method has been packaged for us Double.compare . It receives a functional interface with a return type, which Double ToDoubleFunction&lt;? super T&gt; can be seen as a Function&lt;? super T, Double&gt; lambda representation student -&gt; student.getHeight() .

Therefore, our sort approach can also be written:

students.sort(Comparator.comparingDouble((student) -> student.getHeight()));

First, for a lambda with only one parameter, the parentheses outside the argument can be omitted:

students.sort(Comparator.comparingDouble(student -> student.getHeight()));

Second, for a lambda method body with only one method invocation, which can be further 类::方法 simplified, the above code can be further simplified to:


Here is a method that invokes the object represented by the argument, similar to the following example:

    • string -&gt; System.out.println(string), can be simplified as System.out::println , here is the parameter as System.out::println the parameter;
    • () -&gt; new HashMap&lt;&gt;(), can be simplified as, there are HashMap::new no parameters, can also be simplified.

The use 类::方法 of this style is not more functional sense, it seems that the function as a parameter to a method of it?

No further examples of these simplified form xxx you may feel difficult to remember, in fact, no memory, most Ides can provide simplified recommendations. Summary

In the world of programming languages, Java is like a moderate middle-aged man, it always puts backward compatibility and stability in the first place, not casually because of some language features or grammatical sugar, but for the language features with significant expected benefits will be decisive attack, generics so, Lambda also is so, Perhaps the introduction of them is not thorough and perfect, but it is practical enough to bring great convenience to the developers. This should also be one of the reasons why the Java language can continue to stay alive!

As for the more complex concepts of functional aspects, there is not much to be described here. Now let's meet reactor.

(3) Lambda and function--response spring's DAO spell device

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.