Deep understanding of lambda expression and functional programming functional interface source code analysis

Keywords: Java ascii Lombok Junit

package com.java.design.java8;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.*;
import java.util.stream.Collectors;


/**
 * @author Chen Yang
 */


@RunWith(SpringRunner.class)
@SpringBootTest
public class FuncInterface {

I. understanding of functional programming

//Understanding of functional programming
//
//Functional interface programming is a further abstraction of business applications
 //In the class method definition, only functional interface needs to be implemented regardless of the logic of business implementation
 //Using Lambda expression to flexibly implement the business logic when the external application calls the business

II. Test method of functional interface

1. Function interface

//  Function
Function<Integer, Integer> sum = integer -> integer + 1;
Function<Integer, Integer> multiply = integer -> integer * integer;


List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);

public int testFunctionCompose(Integer integer) {

    return sum.compose(multiply).apply(integer);
}

public int testFunctionAndThen(Integer integer) {

    return sum.andThen(multiply).apply(integer);
}

2. BiFunction interface

//  BiFunction

BiFunction<Integer, Integer, Integer> subtract = (first, last) -> first - last;

public int testBiFunctionAndThen(Integer first, Integer last) {
    return subtract.andThen(multiply).apply(first, last);
}

3. BinaryOperator interface

//  BinaryOperator

BinaryOperator<Integer> binaryOperator = (first, last) -> first - last;

public int testBinaryOperator(Integer first, Integer last) {
    return binaryOperator.apply(first, last);
}

public String testMinBy(String first, String last, Comparator<String> comparator) {
    return BinaryOperator.minBy(comparator).apply(first, last);
}

public String testMaxBy(String first, String last, Comparator<String> comparator) {
    return BinaryOperator.maxBy(comparator).apply(first, last);
}
//comparator

//Compare the length of a string
Comparator<String> length = (first, last) -> first.length() - last.length();
//Compare string initial ASCII size
Comparator<String> asc = (first, last) -> first.charAt(0) - last.charAt(0);

4. Predict interface

//  Predicate

public List<Integer> testPredicate(Predicate<Integer> predicate) {
    return list.stream().filter(predicate).collect(Collectors.toList());
}


public Predicate<String> isEqual(Object object) {
    return Predicate.isEqual(object);
}

public Predicate<Integer> notPredicate(Predicate<Integer> predicate) {
    return Predicate.not(predicate);
}

public List<Integer> testPredicateNegate(Predicate<Integer> predicate) {
    return list.stream().filter(predicate.negate()).collect(Collectors.toList());
}


public List<Integer> testPredicateAnd(Predicate<Integer> first, Predicate<Integer> last) {
    return list.stream().filter(first.and(last)).collect(Collectors.toList());
}

public List<Integer> testPredicateOr(Predicate<Integer> first, Predicate<Integer> last) {
    return list.stream().filter(first.or(last)).collect(Collectors.toList());
}

5. Supplier interface

//  Supplier

@Data
@AllArgsConstructor
@NoArgsConstructor
private class Student {

    private Integer id;

    private String name;

    private String sex;

    private Integer age;

    private String addr;

    private Double salary;

}

III. test results

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.2.RELEASE)

2019-01-31 11:51:58.460  INFO 12080 --- [           main] com.java.design.java8.FuncInterface      : Starting FuncInterface on DESKTOP-87RMBG4 with PID 12080 (started by 46250 in E:\IdeaProjects\design)
2019-01-31 11:51:58.461  INFO 12080 --- [           main] com.java.design.java8.FuncInterface      : No active profile set, falling back to default profiles: default
2019-01-31 11:51:58.988  INFO 12080 --- [           main] com.java.design.java8.FuncInterface      : Started FuncInterface in 0.729 seconds (JVM running for 1.556)
--------------------Understanding of Function interface---------------------

65
81
 ------------------Understanding of BiFunction interface---------------------

64
 -------------------Understanding of predict interface---------------------

Get a set that meets the criteria: greater than 4
[5, 6, 7, 8, 9]
------------------------------

Get the set satisfying the condition: greater than 4 and even
[6, 8]
------------------------------

Get the set that meets the conditions: more than 4 negates
[1, 2, 3, 4, 0]
------------------------------

Get the set that meets the condition: greater than 4 or even
[2, 4, 5, 6, 7, 8, 9, 0]
------------------------------

Use the Equals method of Objects to determine whether the Objects are the same
true
------------------------------

Predict. Not() returns (predict < T >) target. Gate(); 
[1, 2, 3, 4, 0]
------------------------------

Double negation for affirmation
[5, 6, 7, 8, 9]
------------------------------

-------------------Understanding of Supplier interface---------------------

FuncInterface.Student(id=1, name=Kirito, sex=Male, age=18, addr=ShenZhen, salary=9.99999999E8)
------------------------------

---------------Understanding of the BinaryOperator interface-------------------

Implementation of subtraction by applying method inheriting BiFunction
10 - 2 = 8
------------------------------

The short string is: Asuna
 The long string is: Kirito
------------------------------

String initial ASCII is smaller: Asuna
 The big one is: Kirito

Process finished with exit code 0

4. See the source code implementation of the essential function interface through the phenomenon

1. Function interface

@Test
public void testFuncInterface() {

    System.out.println("--------------------Function Interface understanding---------------------\n");


    //  Understanding of Function interface

    //  public interface Function<T, R>
    //  R apply(T t);
    //  Represents a function that accepts one argument and produces a result.
    //  A function: receive a parameter and return a result
    //  T input type R output type

    /*default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
     * Returns a composed function that first applies the {@code before}
     * function to its input, and then applies this function to the result.
     * If evaluation of either function throws an exception, it is relayed to
     * the caller of the composed function.
     */
    //  Input -- > beforefunction() processing -- > the result is used as the input parameter of the next function apply() to form a series call of the functional interface
    //  beforeFunction is called before the current function is applied


    /*default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
    * Returns a composed function that first applies this function to
    * its input, and then applies the {@code after} function to the result.
    * If evaluation of either function throws an exception, it is relayed to
    * the caller of the composed function.
    */
    //  Input -- > apply() process -- > get the result as the input parameter of the next function after.apply() to form a series call of the functional interface
    //  afterFunction is called after the current function is applied


    /*static <T> Function<T, T> identity() {
        return t -> t;
     * Returns a function that always returns its input argument.
    }*/
    //  Always return input parameters

    //  Conclusion:
    //  Function 1. Compose (function2) execution order -- > beforefunction() --- > thisfunction() --- function2 -- > function1
    //  function1.andThen(function2) execution order -- > thisfunction() --- > afterfunction() --- function1 -- > function2
    //  The operation result of the previous function is the input parameter of the next function
    //  To understand the operation time, you can compare @ Before and @ After in Junit

    System.out.println(this.testFunctionCompose(8));
    System.out.println(this.testFunctionAndThen(8));

2. BiFunction interface

System.out.println("------------------BiFunction Interface understanding---------------------\n");


//  Understanding of BiFunction interface

//  @FunctionalInterface
//  public interface BiFunction<T, U, R> {

//   R apply(T t, U u);
//   A function: receive two parameters and return a result

/*
    default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
    Objects.requireNonNull(after);
    return (T t, U u) -> after.apply(apply(t, u));
        }
    }
*/
//   It can be proved that BiFunction does not have the compose method by using the counter evidence method (hint: parameters and return values)
//   Applying two parameters to BiFunction will only get one return value, which will be the parameter passed in as Function
//   biFunction.andthen(function)

System.out.println(this.testBiFunctionAndThen(10, 2));

3. Predict interface

System.out.println("-------------------Predicate Interface understanding---------------------\n");


//   public interface Predicate<T> {
//   Represents a predicate (boolean-valued function) of one argument.


/*
 *    Evaluates this predicate on the given argument.
 *
 *    Receive a judgment to determine whether the expected condition is met and return true false
 *    boolean test(T t);
 */
System.out.println("Get a set that meets the criteria: greater than 4");
System.out.println(this.testPredicate(in -> in > 4));
System.out.println("------------------------------\n");

  /*
   *    Returns a composed predicate that represents a short-circuiting logical
   *    AND of this predicate and another.  When evaluating the composed
   *    predicate, if this predicate is {@code false}, then the {@code other}
   *    predicate is not evaluated.
   *
   *     Short circuit logic and calculation
   *        default Predicate<T> and(Predicate<? super T> other) {
   *             Objects.requireNonNull(other);
   *             return (t) -> test(t) && other.test(t);
  }*/

System.out.println("Get the set satisfying the condition: greater than 4 and even");
System.out.println(this.testPredicateAnd(in -> in > 4, in -> in % 2 == 0));
System.out.println("------------------------------\n");

/*
 *    Returns a predicate that represents the logical negation of this
 *    predicate.
 *
 *     Take inverse
 *    default Predicate<T> negate() {
 *         return (t) -> !test(t);
 *     }
 */
System.out.println("Get the set that meets the conditions: more than 4 negates");
System.out.println(this.testPredicateNegate(in -> in > 4));
System.out.println("------------------------------\n");



/*
 *    Returns a composed predicate that represents a short-circuiting logical
 *    OR of this predicate and another.  When evaluating the composed
 *    predicate, if this predicate is {@code true}, then the {@code other}
 *    predicate is not evaluated.
 *
 *    Short circuit logic or calculation
 *    default Predicate<T> or(Predicate<? super T> other) {
 *        Objects.requireNonNull(other);
 *        return (t) -> test(t) || other.test(t);
 *     }
 */
System.out.println("Get the set that meets the condition: greater than 4 or even");
System.out.println(this.testPredicateOr(in -> in > 4, in -> in % 2 == 0));
System.out.println("------------------------------\n");


/*
 *     Returns a predicate that tests if two arguments are equal according
 *     to {@link Objects#equals(Object, Object)}.
 *
 *      Judge whether two Objects are the same according to the equals method of Objects
 *       static <T> Predicate<T> isEqual(Object targetRef) {
 *       return (null == targetRef)
 *            ? Objects::isNull
 *            : object -> targetRef.equals(object);
 *            }
 */
System.out.println("Use Objects Of Equals Method to judge whether the objects are the same");
System.out.println(this.isEqual("Kirito").test("Kirito"));
System.out.println("------------------------------\n");



/*
 *      Returns a predicate that is the negation of the supplied predicate.
 *      This is accomplished by returning result of the calling
 *      {@code target.negate()}.
 *
 *      Returns the negation of the supplied predicate
 *      @SuppressWarnings("unchecked")
 *      static <T> Predicate<T> not(Predicate<? super T> target) {
 *               Objects.requireNonNull(target);
 *               return (Predicate<T>)target.negate();
 *          }
 *      }
 */
System.out.println("Predicate.not()Return(Predicate<T>)target.negate(); ");
System.out.println(testPredicate(this.notPredicate(integer -> integer > 4)));
System.out.println("------------------------------\n");

System.out.println("Double negation for affirmation");
System.out.println(testPredicateNegate(this.notPredicate(integer -> integer > 4)));
System.out.println("------------------------------\n");

4. Supplier interface

System.out.println("-------------------Supplier Interface understanding---------------------\n");

/*
 *     Represents a supplier of results.
 *
 *     public interface Supplier<T> {
 *                 T get();
 *     }
 */

//  Constructor reference constructor interface instance
//  Using the Supplier interface Student class must have a construction method with or without parameters

//  Supplier<Student> studentSupplier = () -> new Student();
Supplier<Student> studentSupplier = Student::new;

Student student = studentSupplier.get();

student.setId(1);
student.setName("Kirito");
student.setSex("Male");
student.setAge(18);
student.setSalary(999999999.0);
student.setAddr("ShenZhen");

System.out.println(student);
System.out.println("------------------------------\n");

5. BinaryOperator interface

        System.out.println("---------------BinaryOperator Interface understanding-------------------\n");


        /*
         *
         *      public interface BinaryOperator<T> extends BiFunction<T,T,T> {
         *
         *      Returns the smaller value between the two comparison parameters
         *      public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {
         *         Objects.requireNonNull(comparator);
         *         return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
         *          }
         *
         *      Returns the larger value between the two comparison parameters
         *      public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
         *          Objects.requireNonNull(comparator);
         *          return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
         *          }
         *      }
         */
        System.out.println("inherit BiFunction Of Apply Method implementation subtraction");
        System.out.println("10 - 2 = "+this.testBinaryOperator(10, 2));
        System.out.println("------------------------------\n");

        System.out.println("The shorter string is:"+this.testMinBy("Kirito","Asuna",length));
        System.out.println("The long string is:"+this.testMaxBy("Kirito","Asuna",length));
        System.out.println("------------------------------\n");


        System.out.println("String initial ASCII The smaller ones are:"+this.testMinBy("Kirito","Asuna",asc));
        System.out.println("String initial ASCII The larger one is:"+this.testMaxBy("Kirito","Asuna",asc));

    }

}

Posted by jordz on Tue, 03 Dec 2019 01:56:08 -0800