For a long time, Java has been an object-oriented language, where everything is an object, and if you want to call a function, it must belong to a class or object, and then be called using that class or object. But in other programming languages, such as js or c++, we can write a function and call it when we need it. This is either object-oriented programming or functional programming.

There is nothing bad about object-oriented programming from a functional point of view, but from a development point of view, object-oriented programming can involve writing many lines of potentially repetitive code. For example, when creating a Runnable anonymous class:

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("do something..."); }};Copy the code

The only really useful part of this code is what’s in the run method. The rest of the code is structured parts of the Java programming language that are not useful, but should be written.

Fortunately, Java8 started with the introduction of functional programming interfaces and Lambda expressions to help us write less and more elegant code

Runnable Runnable = () -> system.out.println ()"do something...");
Copy the code

Functional interfaces

An Interface class has only one abstract method called a FunctionalInterface. Most Functional interfaces in the JDK are marked with the @functionalInterface annotation, The @functionalInterface annotation is not required for all functional interfaces, but it is used to distinguish between functional interfaces. However, if the annotation is used, there will be a compilation error if there are multiple abstract methods inside.

Error:(3, 1) Java: unexpected @functionalinterface annotation XXX is not a FunctionalInterface found multiple non-overwritten abstract methods in interface XXXCopy the code

When a class is a functional interface, we can instantiate it directly using a Lambda expression without having to write a lot of template code.

Writing:

// Class name variable = (parameter) -> (function body) // such as FunctionTesttest = () -> { };
Copy the code

Built-in functional interface

There are already some standard functional interfaces built into the JDK, under the java.util.function package, that meet our needs in most cases. Interfaces under a package are generally generic. If we want to write a new functional interface, we can first check to see if it is already provided under the package.

So what interfaces does this package provide?

  • The four most common ones are Function, Consumer, Supplier, and Predicate. Standard INPUT output, the way elegant code recommends it
    • Function: a scenario with one incoming parameter and one outgoing parameter.
    • Consumer: An in, but no out
    • Supplier: No input, one input
    • Predicate: Can be thought of as a special Function, with an incoming parameter and an outgoing parameter of type bool.
  • A functional interface with two incoming parameters, that is, two incoming parameters and one outgoing parameter.BiFunction<T, U, R>The most typical use case is Java’s Map method.
    • BiFunction: two in arguments and one generic out argument
    • ToDoubleBiFunction ToIntBiFunction, ToLongBiFunction. Two incoming arguments, return the outgoing arguments of the original type
        HashMap<String, Object> map = new HashMap<>();
        map.put("a", 1); map.put("b", 2); map.replaceAll((o, o2) -> o + o2.toString()); System.out.println(map.values())Copy the code
  • An unary functional interface, which can be thought of as a special Function interface, has the same type for incoming and outgoing parameters. UnaryOperator, a conversion of the same type.

  • The primitive type Function, because the Java primitive type or the primary type, int, short, double, etc., cannot be used as a generic argument. These primitive types are officially provided with a special functional interface

    • As an int: IntFunction, IntComsumer,IntSupplieer, IntPredicate, IntToDoubleFcuntion, IntToLongFunction, IntUnaryOperator, ToIntFunction

Official:

Docs.oracle.com/javase/8/do…

Lambda expressions

If we understand functional interfaces, we also understand Lambda expressions to some extent. Lambda expressions are equivalent to the use of functional interfaces. We can’t just write interfaces but not use them.

Although Java supports functional interfaces, Java functions are still embedded in classes and cannot exist in isolation, but since a functional interface is only an abstract function, it is clear that there is a method to use. So the compiler can automatically deduce which method to use without writing extra template code:

Runnable runnable = () -> System.out.println("do something...");
Copy the code
  • First, Runnable is a functional interface, so we can instantiate it using a Lambda expression
  • Since the run method has no arguments, the lambda expression is:(argument) -> {body}, the parameter is empty(a)
  • For the body of the function, if we only have one line of code, we can omit {}.

In addition to Lambda expressions for function calls, there are some method reference operations that can be explored using ::, which refer to methods or constructors without actually instantiating objects

String::toUpperCase
System.out::println
"abc"::length
ArrayList::new
int[]::new
Copy the code

Official:

www.oracle.com/webfolder/t…

Docs.oracle.com/javase/tuto…

The last

Functional programming in Java goes far beyond what is expressed here and requires a lot more exploration. Of course, this section mainly introduces the functional interface of Java, has been in the java.util. Function package under the common functional interface, finally made a simple description of lambda expressions.

Reference address: tutorials.jenkov.com/java/lambda… www.baeldung.com/java-8-lamb… www.baeldung.com/java-8-func… Docs.oracle.com/javase/8/do…