This article source: making here | | GitEE, click here

1. Functional concept

Functional programming is a kind of structured programming paradigm, the main idea is to write the operation process as much as possible in a series of nested function calls. The conceptual representation of functional programming has a very abstract feel and can be based on examples:

Public class Function01 {public static void main(String[] args) {(x+y) * c int x1 = 2; int y1 = 3 ; int c1 = 4 ; int sum1 = x1 + y1 ; int res1 = sum1 * c1 ; System.out.println("res1 = "+res1); }}

Calculations are done in a procedural-based manner, with the above block of code focusing on describing the execution of the program.

In looking at the function-based approach to the solution:

Public static void main(String[] args) {public static void main(String[] args) {public static void main(String[] args) {public static void main(String[] args) "+ func01 (2 and 4)); } private static int func01 (int x,int y,int c){ return (x+y)*c; }}

The core elements of functional programming: passing in parameters, executing logic, and returning a value, or no return value.

The functional style of programming focuses on describing the execution logic of a program, not the execution process.

Functional programming also reduces the number of temporary variables created and makes the code style cleaner and cleaner than the above calculation process.

II. Functions and Methods

There is a functional programming style in the Java language, but in Java code there are no functions, instead they are called: methods;

public class Function03 { public static void main(String[] args) { Func03 func03 = new Func03(); func03.add(2); System.out.println(func03.res1); } } class Func03 { public int res1 = 0 ; public void add (int a1){ this.res1 = a1 +1 ; }}

Class definitions refer to data types, and objects instantiated by a class can call methods and data inside the class, which is intuitive.

However, there is a difference between static and non-static methods. Static methods belong to the class and can be used before the class is instantiated.

Non-static methods can access any member variable and method in the class and must be objects instantiated by the class to be called.

The basics of JDK functions

1. Lambda expression

Lambda expressions, also known as closures, are the most important new feature driving Java8’s release, allowing functions to be passed as arguments to a method.

Here is a sharp contrast between the syntax of a Lambda expression and its traditional usage.

public class Lambda01 { interface LambdaOpera { int operation(int a, int b); } public static void main(String[] args) { LambdaOpera lambdaOpera = new LambdaOpera(){ @Override public int operation(int a, int b) { return a * b ; }}; System. The out. Println (lambdaOpera. Operation (3, 2)); LambdaOpera lambdaOpera01 = (int a, int b) -> a + b; LambdaOpera lambdaOpera02 = (int a, int b) -> a - b; System. The out. Println (lambdaOpera01. Operation (3, 2)); System. The out. Println (lambdaOpera02. Operation (3, 2)); }}

Let’s look at an intuitive example of how creating threads based on Lambda can make code more compact and compact:

public class Lambda02 { public static void main(String[] args) { new Thread(new Runnable() { @Override public void run()  { for (int i = 0; i < 2; i++) { System.out.println(i); } } }).start(); New Thread(() -> {for (int I = 0; i < 2; i++) { System.out.println(i); } }).start(); }}

Take a look at the structure of the Runnable interface:

FunctionalInterface is marked on an interface to indicate that the interface is functional and that it contains only one abstract method,

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

Lambda expressions themselves can be understood as the implementation of an interface, where Runnable is the complete Lambda expression declaration:

public class Lambda04 {
    public static void main(String[] args) {
        Runnable runnable = () -> {
            System.out.println("run one...");
        };
        Thread thread = new Thread(runnable);
        thread.start();
    }
}

One of the most intuitive things Lambda expressions do is make the code extremely compact and can be passed as arguments.

2. Functional Interface

Lambda expressions have many advantages, but using them requires defining interfaces to code them, which makes the expressions heavyweight again. Java8 itself already provides several common functional interfaces.

  • Function: Enter a parameter and return a result;
  • Consumer: Input a parameter and returns no results;
  • BiFunction: Enter two arguments and return a result;
  • Biconsumer: Enter two parameters and return no results;
public class Lambda05 { public static void main(String[] args) { Function<Integer, Integer> function01 = x -> x * 2; System.out.println(function01.apply(2)); BiFunction<Integer, Integer, Integer> function02 = (x, y) -> x * y; System.out.println(function02.apply(2, 3)); Consumer<String> consumer01 = msg -> System.out.println("msg:"+msg); consumer01.accept("hello"); BiConsumer<String,Integer> consumer02 = (msg,i) -> System.out.println(msg+":"+i); consumer02.accept("world",3); }}

If you face more complex business requirements, you can customize functional interfaces to address them.

Four, Optional classes

1. NULL judgment

Optional class is an application of Java functional programming, mainly used to solve the common null pointer exception problem.

Null-pointer exceptions are common in many areas of Java programming development, and to avoid them requires a lot of judgment:

public class Optional01 { public static void main(String[] args) { User user = new User(1,"hello") ; if (user ! = null){ if (user.getName() ! = null){ System.out.println(user.getName()); }}}}

In order to ensure that the program does not throw a low level error such as a null pointer, the program can be NULL everywhere, the code is obviously redundant and cumbersome.

2. Optional application

An object created based on the Optional class may contain null and null values, as well as throw the corresponding exception:

public class Optional02 {
    public static void main(String[] args) {
        // NoSuchElementException
        Optional<User> optionalUser = Optional.empty();
        optionalUser.get();
        // NullPointerException
        Optional<User> nullOpt = Optional.of(null);
        nullOpt.get();
    }
}

So if you don’t know exactly what the object is, use ofNullable() :

public class Optional03 { public static void main(String[] args) { User user = new User(1,"say"); Optional<User> optionalUser = Optional.ofNullable(user); if (optionalUser.isPresent()){ System.out.println(optionalUser.get().getName()); } User user1 = null ; User createUser = Optional.ofNullable(user1).orElse(createUser()); System.out.println(createUser.getName()); User user2 = null ; Optional.ofNullable(user2).orElseThrow( () -> new RuntimeException());; } public static User createUser (){ return new User(2,"hello") ; }}

Optional combines chained methods with Lambda expressions to greatly simplify the amount of code in the application:

Public class Optional04 {public static void main(String[] args) {public static void main(String[] args) {public static void main(String[] args) {public static void main(String[] args); // user = null ; String name = Optional.ofNullable(user) .map(u -> u.getName()).orElse("c++"); System.out.println(name); OptUser01 = Optional. OfNullable (User). Filter (u -> u.getName()! = null && u.getName().contains("c++")); // NoSuchElementException System.out.println(optUser01.get().getName()); }}

Optional provides a variety of methods for NULL handling, which can simplify a lot of code judgment, but it is used in a very different style than before.

Five, the Stream flow

If Optional simplifies a lot of NULL, then the Stream API simplifies a lot of collection traversal, also based on functional programming.

The above is the Stream interface inheritance relationship as shown in the figure. It also provides some specific interfaces and a larger wrapper interface. Through the source code review, we can see that it is also closely related to functional programming.

public class Stream01 {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("hello", "java");
        stream.forEach(str -> System.out.print(str+";"));
    }
}

Streams are used in conjunction with function interfaces, which in turn simplify the code using Lambda expressions. The Stream in Java8 greatly simplifies the code complexity used by collections.

Public class Stream02 {public static void main(String[] args) {// 1, convert Stream List<String> List = Arrays.aslist (" Java +;" , c + + ";" , "net;" ); list.stream(); ForEach (list.stream().foreach (System.out::print); Intstream.rangeclosed (2,3).map(x->x+1).foreach (System.out::println); / / 4, the filter to filter the list. The stream () filter (STR - > STR. The contains (" + "). The forEach (System. Out: : print). // 5, DISTINCT Integer[] arr = new Integer[]{3, 1, 3, 1, 2,4}; Stream.of(arr).distinct().forEach(System.out::println); * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / / 7, collect a List < String > newList = List. The stream () filter (STR - > STR. The contains (" + ")). Collect (Collectors. ToList ()); newList.stream().forEach(System.out::print); }}

Before the Stream-related API, the manipulation and traversal of a collection would have generated a lot of code, which would have been simplified by the functional programming of the Stream-related API collection and the Lambda expression style.

Six, the source code address

Making address GitEE, https://github.com/cicadasmile/java-base-parent, https://gitee.com/cicadasmile/java-base-parent

Read labels

【 JAVA Foundation 】【 Design Patterns 】【 Structure and Algorithms 】【Linux System 】【 Database 】

[Distributed Architecture] [Micro Services] [Big Data Components] [SpringBoot Advanced] [Spring&Boot Foundation]

【 Data Analysis 】【 Technical Map 】【 Workplace 】