Detailed introduction of Java function programming

  • 2021-12-12 08:36:13
  • OfStack

Directory 1. Function Programming Lambda1, Interface 2. Java Function Interface 1, Predicate2, Consumer3, Function4, Supplier3. Type Checking 1, Capturing Lambda4. Method Reference 1, Constructor Reference 2, Combination Lambda3, Comparators4, Functions5. Summary

Foreword:

Functional programming is a programming paradigm in which programs are constructed by applying and combining functions. It is a declarative programming paradigm, in which function definitions are expression trees, and each expression tree returns 1 value instead of a series of command statements that change the state of the program

Java8 Introduced Lambda Functional programming in the form. Terminology Lambda From Lambda Calculus, used to describe calculation.

1. Functional programming Lambda

We can put lambda An expression is treated as an anonymous function that can be assigned to a variable and passed to a method that accepts the function interface as an argument. Lambda The expression has no name, but it has a parameter list, a body, and a return type.

(parameters) -> expression

lambda Expressions can be used in the context of function interfaces.

1. Interface

A function interface is an interface that specifies only one abstract method.


public interface Comparator<T> {                           
    int compare(T o1, T o2);
}
public interface Runnable {                                
    void run();
}


Lambda Expressions allow us to directly inline the implementation of an abstract method that provides a function interface and treat the entire expression as an instance of the function interface.

Function descriptor:

We call the signature of the abstract method of the function interface a function descriptor. The function descriptor describes the signature of the lambda expression. For example, we can think of the function descriptor of Runnable as ()- > void, because it has an abstract method that accepts nothing and returns nothing (void).

2. Java function interface

1. Predicate

Predicate < T > Interface defines a file named Lambda0 That accepts an object of generic type T and returns a Boolean value. This interface can be used to represent Boolean expressions that use T type objects.

Function descriptor: Lambda1


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

2. Consumer

Lambda2 Interface defines a file named Lambda3 That accepts an object of generic type T and returns no result (void). We can use this interface when we need to access and perform some operations on objects of type T.

Function descriptor: Lambda4

3. Function

Lambda5 Interface defines a file named Lambda6 That takes an object of generic type T as input and returns an object of generic type R. When we need to define a lambda You can use this interface when mapping information from input objects to output.

Function descriptor: Lambda8

4. Supplier

Interface Lambda9 Defines a file named Lambda0 That accepts nothing and returns an object of type T.

Function descriptor: Lambda1

Lambda2

A primitive interface is a dedicated interface used to avoid automatic boxing when the input or output is a primitive.


public interface IntPredicate {
    boolean test(int t);
}

3. Type checking

lambda The type of is derived from using the lambda Deduced from the context of. In context lambda The type required by an expression (for example, a method parameter passed to it or a local variable assigned to it) is called the target type. Lambda An expression can get its target type from an assignment context, a method invocation context (parameters and returns), and a cast context.


Object o = (Runnable) () -> System.out.println("Hello");

1. Capturing Lambda

lambda Instance variables and static variables can be captured (referenced in their bodies) without restriction. But when local variables are captured, they must be explicitly declared as final or actually Lambda8 .

Why do we have this restriction?

Instance variables are stored on the heap, while local variables are on the stack. If lambda can directly access a local variable and lambda is used in a thread, the thread using lambda can attempt to access the variable after the thread allocating the variable has unallocated it. Therefore, Java implements access to a free local variable as access to its copy, not to the original variable. If the local variable is assigned only once, it makes no difference, so there are restrictions.

4. Method references

There are three main method references:

A method reference to a static method. For example Lambda9 A method reference to an instance method of any type. Example Lambda0 A method reference to an instance method of an existing object or expression. Example Lambda1 , of which Lambda2 Is a method getRank Adj. Lambda2 Local variables of type

List<String> list = Arrays.asList("a","b","A","B");
list.sort((s1, s2) -> s1.compareToIgnoreCase(s2));

It can be written as


List<String> list = Arrays.asList("a","b","A","B");
list.sort(String::compareToIgnoreCase);

1. Constructor reference

You can use ClassName:: new to reference existing constructors

Supplier<List<String>> supplier = ArrayList::new; And Supplier<List<String>> supplier = () -> new ArrayList<>() Same;

2. Combine Lambda

Many functional interfaces contain functions that can be used to combine lambda The default method of the expression. Combination sample-

Combine two predicates into a larger predicate and perform or operation between the two predicates
Reverse or chain comparator

3. Comparators

Arrange students in reverse order


Comparator<Student> c = Comparator.comparing(Student::getRank);
students.sort(comparing(Student::getRank).reversed()); 

Sort students by name (reverse), and then arrange them in reverse order


students.sort(comparing(Student::getName).reversed()
        .thenComparing(Student::getRank)); 
Predicates


The Predicates interface includes three methods: negate , and , and or Which can be used to create more complex predicates.


Predicate<Integer> naturalNumber = i -> i > 0;                                     
Predicate<Integer> naturalNumberLessThanHundred = naturalNumber.and( i -> i < 100);

4. Functions

The function interface has two default methods, andThen And compose .

Consider f(x) = x2 and g(x) = x3 + 1 then

g(f(x)) ->


Function<Integer,Integer> square = n -> n*n;                         
Function<Integer,Integer> squareAndCube = square.andThen(n -> n*n*n+1);
System.out.println(squareAndCube.apply(2));  
65                        


f(g(x)) ->


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

0

Applying Lambda

Let's see how to write a general method based on veratain Property filters 1 group of books as sql Adj. where Clause).


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

1

Lambda Expression filters different books through different filters


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

2

STEP 5 Summarize

lambda An expression can be considered an anonymous function and can be used in the context of a function interface. A function interface is an interface that specifies only one abstract method.


Related articles: