Java8 functional programming learning summary

What is functional programming

Functional concept

Functional programming is not a unique feature of Java 8. It is a programming idea like object-oriented programming.

The term function in functional programming is a function in the mathematical sense rather than a method defined in programming (method/function). In the category of mathematics, the definition of a function is as follows:

Given a number set A, assuming the element is x, apply the corresponding law f to the element x in A, denoted as f(x), to get another number set B, assuming that the element in B is y, then y and The equivalent relationship between x can be expressed by y=f(x).

The return value of a function depends only on the input parameters and not on other external states. As long as the input is certain, the output is certain. This can be felt in the use of java Stream:

  1. The returned result is a new object, which does not affect the original object. The new object is a mapping of the original object.

  2. From the beginning of the call to the end of the call, no external variables are involved. The execution result of the same input parameter is always the same.

The difference between functional and imperative

Compared with the usual imperative programming, the main difference is that there are intermediate variables in the execution of imperative programming, which are used to store temporary states. Each step of the program is an exact instruction for the computer; while functional programming uses functions Expressions maintain calculation relationships. This functional relationship is more in line with human mathematical logic and is therefore easier to be understood by people. However, if it is not processed, the computer cannot understand such complex mathematical logic. What it needs is an exact step by step Instructions, so the final functional program is compiled into machine language instructions (Von Neumann machine) for execution. Therefore, functional programming is called syntactic sugar because it makes code logic easier to understand for programmers.

In summary, the core of functional programming thinking is map. When more complex logic is required, the function is passed as an input parameter to another function, combined into a more complex function expression, and the function is passed as a parameter to another function. A function is also a distinctive feature of functional programming.

How to functional programming in java

Inner class

Java is an object-oriented language. The encapsulation of the three major characteristics of Java emphasizes the use of abstract data types to encapsulate data and data-based operations to form an indivisible and independent entity, which is javaBean. In the concept of functional programming, there are no objects and values, only functional expressions, everything is a formula, so how to integrate functional programming with java? The answer is: internal class, for example:

@FunctionalInterface
interface MyFunctionInterface<T> {
    void doSome(T t);
}
​
public class LambdaTest {
    public static void main(String[] args) {
        //1
        MyFunctionInterface<String> myFunctionInterface = new MyFunctionInterface<String>() {
            @Override
            public void doSome(String s) {
              System.out.print(s);
            }
        };
        //2
        MyFunctionInterface<String> myFunctionInterface_lambda =(s)->System.out.print(s);
        //3
        MyFunctionInterface<String> myFunctionInterface_simple =System.out::println;
        myFunctionInterface.doSome("test");
    }
}
  • First define an interface with only one custom abstract method, @FunctionalInterface can be marked or not. The input parameter of the method is the paradigm T, and the specific type is determined by the user.

  • LambdaTest calls MyFunctionInterface to execute custom logic, here is a simple print.

  • The position of Note 1 is the normal usage of the inner class.

  • As you can see in the position of Note 2, System.out.print is of void type, and the input parameter is string; doSome is also of void type, and the input parameter is string. So you can use lambda to simplify and change the internal class writing. At this time, you can clearly know from the senses that myFunctionInterface_lambda is the function of output printing.

  • The position of Note 3 has been simplified again for Type 2. At this time, myFunctionInterface_simple is assigned not like an object, but more like a function , although it is still an internal class object when it is finally compiled.

  • The most common example is the Runnable interface, which also has only one run method

Runnable r=()->{
  ...
}

Functional interface

The interface used above is called a functional interface. A functional interface (Functional Interface) is an interface that has one and only one abstract method (except the public method of the Object class), but can have multiple non-abstract methods, for example, there can be an equals method, as shown below:

//这个是正确的用法,只含有一个自定义抽象的方法
@FunctionalInterface
interface Compare<T> {
    void compare(A t1, A t2);
}
​
//这个也是正确的用法,虽然接口有两个方法,但是equals是顶级父类Object的public方法,这是允许的
@FunctionalInterface
interface Compare<T> {
    void compare(A t1, A t2);
    boolean equals(Object obj);
}
​
//这是错误的,因为clone虽然是父类的方法,但是是protected类型的,而不是public类型的
@FunctionalInterface
interface Compare<T> {
    void compare(A t1, A t2);
    Object clone();
}
​
//这是正确的用法,函数式接口允许由默认方法。函数式接口是java新增的支持,default可以兼容之前的代码。
@FunctionalInterface
interface Compare<T> {
    void compare(A t1, A t2);
    default void init(){
    }
}

@FunctionInterface does not have to be annotated, but if it is annotated, it can give you an error at compile time.

Since it is implemented using internal classes, why is there only one method restriction? Can inner classes have multiple methods? Or use the first example to explain:

interface MyFunctionInterface<T> {
    void doSome(T t);
    void doOther();
}
public class LambdaTest {
    public static void main(String[] args) {
      MyFunctionInterface<String> myInterface=new MyFunctionInterface<String>() {
            @Override
            public void doSome(String s) {
​
            }
​
            @Override
            public void doOther() {
​
            }
        };
    }
 }

As shown in the code above, the internal class does not limit the number of methods of the interface, but when there are multiple methods, Lambda expressions can no longer be used to simplify, and it cannot be converted into functional style code. Therefore, the functional interface only allows another custom abstract method to match the use of Lambda expressions.

Based on the above, we know that writing functional code in java needs to pay attention to the following points:

  1. To define a functional interface, the interface has only one custom abstract method.

  2. @FunctionalInterface can be written or not, and it will be checked before compilation.

  3. Combined with lambda, design functional style.

  4. java.util.function It contains many classes to support functional programming in Java. There are 43 functional interfaces in the package, but the most important ones are these four:

    (1) Functional interface: R Function<T,R> operates on type T parameters and returns R type parameters, including the method R apply(T t)
    (2) Assertion interface: boolean Predicate<T> assertion type interface, right Type T for conditional filtering operation, return boolean, including method boolean test(T t)
    (3) Supply interface: T Supplier<T> Return T type parameter, the method is T get()
    (4) Consumer interface: void Consumer <T> Operation on type T parameters, no result is returned, including method void accept(T t)

Use of Stream

Stream is an excellent practice of functional programming. For the processing of collection classes, the code implemented using stream is clear and elegant. Several important methods and concepts are mainly recorded here

  1. map: mapping

    As the name implies, given a value converted to another value, the mapping has the most significant feature of the function.

    //给一个用户列表List<UserInfo>,需要取出所有的用户Id:
    List<UserInfo>userList=...;
    List<Integer>userIdList=userList.stream().map(UserInfo::getUserId).collect(Collectors.toList());

     

  2. reduce: sum operation

    The values ​​in the collection can be aggregated together according to rules. When our collect collector cannot handle special logic, we can consider using reduce to customize the collector.

    //给一串数字,将每个字连接起来,“,”分隔就是规则
    Stream.of("1", "2", "3", "4").reduce((x, y) -> x+","+y).orElse(null);

     

  3. filter: filter

    Used to filter eligible sub-collections from the collection

    //筛选得分大于60的用户:
    List<UserInfo>userList=...;
     List<UserInfo> result=userList.stream().filter(user->user.getScore()>60).collect(Collectors.toList());

     

  4. collect: collect

    The collection relies on the Stream class to manage the function calculation relationship in the process of circulation. When taking a value, the value in the Stream is "collected" through collect. In addition to the above can collect the result into a List, toSet and toMap are commonly used.

  5. parallerStream和CompletableFuture

    CompletableFuture is commonly used in parallel programming. When a thread pool is given, it will process tasks according to the set thread pool. When the thread pool is not specified, ForkJoinPool. commonPool () is used by default .

    ParallerStream is a Stream for processing parallel tasks. It uses both the main thread and the threads created by ForkJoinPool.commonPool. When ForkJoinPool is not enough, it will use the main thread to process tasks. In extreme cases, parallerStream can become a single-threaded Stream.

Pros and cons of functional programming

advantage

A higher degree of reuse, the object-oriented reuse level is the class, the functional reuse level is the function, and the functions are combined into new functions through parameter passing.

There is no state inside the function, and there is no intermediate value in the operation process, which saves the entanglement when naming variables.

The function does not rely on external state, does not share state (between multiple threads), and there is no competition, and there is no need to use locks to protect variable states, and there will be no deadlocks, which can be better concurrent .

Lazy evaluation, when the expression is assigned to the variable, the value of the expression is not calculated, only when the variable is used for the first time.

Disadvantage

For Java, a large number of functional interfaces with only one interface need to be written.

Functional programming has no intermediate variables, so loops cannot be used (such as for loops need to be indexed, while loops need to jump out of conditions). Instead, recursive calling functions are used. Recursion may cause stack overflow problems, because every function call is Need to be stacked.

In complex business scenarios, it is impossible to express everything as a function and deal with the relationships between things. Object-oriented still has the dominant advantage.

Which scenarios are suitable for functional programming

data processing

Logical relation operation

Abstract module of processing flow

Use caution in business scenarios

Guess you like

Origin blog.csdn.net/u013821237/article/details/104209788