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 陈杨
 */


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

一、函数式编程的理解

//  函数式编程的理解
//
//  函数接口式编程 是 对 业务应用的进一步抽象
//  在类方法定义中 只需实现FunctionalInterface 而不管业务实现的逻辑
//  在外部应用 调用该业务时 使用Lambda表达式 灵活实现其业务逻辑

二、 函数式接口的测试方法

1、Function接口

//  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接口

//  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接口

//  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<String> length = (first, last) -> first.length() - last.length();
//比较字符串首字母ASCII码大小
Comparator<String> asc = (first, last) -> first.charAt(0) - last.charAt(0);

4、Predicate接口

//  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接口

//  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;

}

三、测试结果

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: 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)
--------------------Function接口的理解---------------------

65
81
------------------BiFunction接口的理解---------------------

64
-------------------Predicate接口的理解---------------------

获取满足条件的集合:大于4
[5, 6, 7, 8, 9]
------------------------------

获取满足条件的集合:大于4且是偶数
[6, 8]
------------------------------

获取满足条件的集合:大于4  取反
[1, 2, 3, 4, 0]
------------------------------

获取满足条件的集合:大于4或是偶数
[2, 4, 5, 6, 7, 8, 9, 0]
------------------------------

使用Objects的Equals方法判断对象是否相同
true
------------------------------

Predicate.not()返回(Predicate<T>)target.negate(); 
[1, 2, 3, 4, 0]
------------------------------

双重否定表肯定
[5, 6, 7, 8, 9]
------------------------------

-------------------Supplier接口的理解---------------------

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

---------------BinaryOperator接口的理解-------------------

继承BiFunction的Apply方法 实现减法
10 - 2 = 8
------------------------------

字符串较短的是:Asuna
字符串较长的是:Kirito
------------------------------

字符串首字母ASCII码较小的是:Asuna
字符串首字母ASCII码较大的是:Kirito

Process finished with exit code 0

四、透过现象看本质 函数式接口的源码实现

1、Function接口

@Test
public void testFuncInterface() {

    System.out.println("--------------------Function接口的理解---------------------\n");


    //  Function接口的理解

    //  public interface Function<T, R>
    //  R apply(T t);
    //  Represents a function that accepts one argument and produces a result.
    //  一个函数:接收一个参数 返回一个结果
    //  T 输入类型 R 输出类型

    /*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.
     */
    //  输入-->beforeFunction()处理-->得到结果作为下一个函数apply()的输入参数  形成函数式接口的串联调用
    //  beforeFunction 在当前函数apply前 进行调用


    /*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.
    */
    //  输入-->apply()处理-->得到结果作为下一个函数after.apply()的输入参数  形成函数式接口的串联调用
    //  afterFunction 在当前函数apply后 进行调用


    /*static <T> Function<T, T> identity() {
        return t -> t;
     * Returns a function that always returns its input argument.
    }*/
    //  总是返回输入参数

    //  总结:
    //  function1.compose(function2)  执行顺序 -->BeforeFunction()-->thisFunction()-->  function2 --> function1
    //  function1.andThen(function2)  执行顺序 -->thisFunction()-->AfterFunction()-->   function1 --> function2
    //  前一个函数的运算结果 作为下一个函数的输入参数
    //  理解运行时机 可以类比 Junit中 @Before 与 @After

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

2、BiFunction接口

System.out.println("------------------BiFunction接口的理解---------------------\n");


//  BiFunction 接口 的 理解

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

//   R apply(T t, U u);
//   一个函数:接收二个参数 返回一个结果

/*
    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));
        }
    }
*/
//   利用反证法 可以证明  BiFunction 没有 compose方法  (提示: 参数 与 返回值)
//   将2个参数应用于BiFunction 只会得到一个返回值 这个返回值会作为Function传入的参数
//   biFunction.andthen(function)

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

3、Predicate接口

System.out.println("-------------------Predicate接口的理解---------------------\n");


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


/*
 *    Evaluates this predicate on the given argument.
 *
 *    接收一个判断 判断是否满足预期条件 返回true false
 *    boolean test(T t);
 */
System.out.println("获取满足条件的集合:大于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.
   *
   *     短路逻辑与计算
   *        default Predicate<T> and(Predicate<? super T> other) {
   *             Objects.requireNonNull(other);
   *             return (t) -> test(t) && other.test(t);
  }*/

System.out.println("获取满足条件的集合:大于4且是偶数");
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.
 *
 *     取反
 *    default Predicate<T> negate() {
 *         return (t) -> !test(t);
 *     }
 */
System.out.println("获取满足条件的集合:大于4  取反");
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.
 *
 *    短路逻辑或计算
 *    default Predicate<T> or(Predicate<? super T> other) {
 *        Objects.requireNonNull(other);
 *        return (t) -> test(t) || other.test(t);
 *     }
 */
System.out.println("获取满足条件的集合:大于4或是偶数");
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)}.
 *
 *      根据Objects的equals方法 来判断两个对象 是否相同
 *       static <T> Predicate<T> isEqual(Object targetRef) {
 *       return (null == targetRef)
 *            ? Objects::isNull
 *            : object -> targetRef.equals(object);
 *            }
 */
System.out.println("使用Objects的Equals方法判断对象是否相同");
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()}.
 *
 *      返回提供的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()返回(Predicate<T>)target.negate(); ");
System.out.println(testPredicate(this.notPredicate(integer -> integer > 4)));
System.out.println("------------------------------\n");

System.out.println("双重否定表肯定");
System.out.println(testPredicateNegate(this.notPredicate(integer -> integer > 4)));
System.out.println("------------------------------\n");

4、Supplier接口

System.out.println("-------------------Supplier接口的理解---------------------\n");

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

//  构造方法引用  构造函数接口实例
//  利用Supplier接口  Student类必须要有无参的构造方法

//  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接口

        System.out.println("---------------BinaryOperator接口的理解-------------------\n");


        /*
         *
         *      public interface BinaryOperator<T> extends BiFunction<T,T,T> {
         *
         *      返回2个比较参数之间的较小值
         *      public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {
         *         Objects.requireNonNull(comparator);
         *         return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
         *          }
         *
         *      返回2个比较参数之间的较大值
         *      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("继承BiFunction的Apply方法 实现减法");
        System.out.println("10 - 2 = "+this.testBinaryOperator(10, 2));
        System.out.println("------------------------------\n");

        System.out.println("字符串较短的是:"+this.testMinBy("Kirito","Asuna",length));
        System.out.println("字符串较长的是:"+this.testMaxBy("Kirito","Asuna",length));
        System.out.println("------------------------------\n");


        System.out.println("字符串首字母ASCII码较小的是:"+this.testMinBy("Kirito","Asuna",asc));
        System.out.println("字符串首字母ASCII码较大的是:"+this.testMaxBy("Kirito","Asuna",asc));

    }

}

陈杨
12 声望3 粉丝

不闻不若闻之,闻之不若见之,见之不若知之,知之不若行之,学至于行而止矣;行之,明也!