Explain in detail how to skillfully use java functional interface

  • 2021-09-11 20:21:07
  • OfStack

1. The Origin of Functional Interfaces

We know that the premise of using Lambda expressions is to have functional interfaces, while Lambda expressions do not care about interface names and abstract method names. Only care about the parameter list and return value type of abstract methods. So in order for us to use more methods of Lambda expressions, a large number of commonly used functional interfaces are provided in JDK


package com.bobo.jdk.fun;

public class Demo01Fun {

    public static void main(String[] args) {
        fun1((arr)->{
            int sum = 0 ;
            for (int i : arr) {
                sum += i;
            }
            return sum;
        });
    }

    public static void fun1(Operator operator){
        int[] arr = {1,2,3,4};
        int sum = operator.getSum(arr);
        System.out.println("sum = " + sum);
    }
}

/**
 *  Functional interface 
 */
@FunctionalInterface
interface Operator{

    int getSum(int[] arr);
}

2. Introduction to functional interfaces

There are functional interfaces provided for us in JDK, mainly in java. util. function package.

2.1 Supplier

For an interface with no parameters and a return value, a type of return data is required for the Lambda expression of.


@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

Use:


/**
 * Supplier  Use of functional interface 
 */
public class SupplierTest {

    public static void main(String[] args) {
        fun1(()->{
            int arr[] = {22,33,55,66,44,99,10};
            //  Calculate the maximum value in the array 
            Arrays.sort(arr);
            return arr[arr.length-1];
        });
    }

    private static void fun1(Supplier<Integer> supplier){
        // get()  Yes 1 Having a return value without parameters   Abstract method 
        Integer max = supplier.get();
        System.out.println("max = " + max);

    }
}

2.2 Consumer

Interface with parameters but no return value. The Supplier interface described above is used to produce data, while the Consumer interface is used to consume data. When using it, you need to specify a generic type to define the parameter type


@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
}

Use: Convert the input data system 1 to lowercase output


public class ConsumerTest {

    public static void main(String[] args) {
        test(msg -> {
            System.out.println(msg + "->  Convert to lowercase: " + msg.toLowerCase());
        });
    }

    public static void test(Consumer<String> consumer){
        consumer.accept("Hello World");
    }
}

Default method: andThen

If the parameters and return values of a method are all Consumer type, then the effect can be achieved. When consuming a data, first do one operation, and then do another operation to realize the combination, and this method is the default method and andThen method in the Consumer interface


 default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }

Specific operations


public class ConsumerAndThenTest {

    public static void main(String[] args) {
        test2(msg1->{
            System.out.println(msg1 + "->  Convert to lowercase: " + msg1.toLowerCase());
        },msg2->{
            System.out.println(msg2 + "->  Convert to uppercase: " + msg2.toUpperCase());
        });
    }


    public static void test2(Consumer<String> c1,Consumer<String> c2){
        String str = "Hello World";
        //c1.accept(str); //  Turn to lowercase 
        //c2.accept(str); //  Turn to capitalization 
        //c1.andThen(c2).accept(str);
        c2.andThen(c1).accept(str);
    }
}

2.3 Function

For interfaces with parameters and return values, Function interface obtains another type of data according to one type of data, the former is called precondition, and the latter is called postcondition. There are parameters and return values.


@FunctionalInterface
public interface Function<T, R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);
}

Use: Pass into 1 string and return 1 number


public class FunctionTest {

    public static void main(String[] args) {
        test(msg ->{
            return Integer.parseInt(msg);
        });
    }

    public static void test(Function<String,Integer> function){
        Integer apply = function.apply("666");
        System.out.println("apply = " + apply);
    }
}

The default method: andThen is also used for combination operations.


default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}
0

The default compose method works in the opposite order to the andThen method

The static method identity returns whatever parameters are entered

2.4 Predicate

Interface with parameters and return value Boolean


@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}
1

Use:


@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}
2

The default method in Predicate provides the logical relationship operation and or negate isEquals method


package com.bobo.jdk.fun;

import java.util.function.Predicate;

public class PredicateDefaultTest {

    public static void main(String[] args) {
        test(msg1 -> {
            return msg1.contains("H");
        },msg2 -> {
            return msg2.contains("W");
        });
    }

    private static void test(Predicate<String> p1,Predicate<String> p2){
        /*boolean b1 = predicate.test(msg);
        boolean b2 = predicate.test("Hello");*/
        // b1  Include H b2  Include W
        // p1  Include H  Simultaneously  p2  Include W
        boolean bb1 = p1.and(p2).test("Hello");
        // p1  Include H  Or  p2  Include W
        boolean bb2 = p1.or(p2).test("Hello");
        // p1  Does not contain H
        boolean bb3 = p1.negate().test("Hello");
        System.out.println(bb1); // FALSE
        System.out.println(bb2); // TRUE
        System.out.println(bb3); // FALSE
    }
}

Related articles: