Java8新特性探索之函数式接口( 二 )

  • 默认方法:default Consumer andThen(Consumer after) , 如果一个方法的参数和返回值全都是 Consumer 类型 , 那么就可以实现效果:消费数据的时候 , 首先做一个操作 , 然后再做一个操作 , 实现组合
  • public class ConsumerTest { /*** 先计算总分 , 再计算平均分*/ @Test public void calculate() {Integer[] fraction = new Integer[] { 65, 76, 85, 92, 88, 99 };consumer(fraction, x -> System.out.println(Arrays.stream(x).mapToInt(Integer::intValue).sum()),y -> System.out.println(Arrays.stream(y).mapToInt(Integer::intValue).average().getAsDouble())); }public void consumer(Integer[] fraction, Consumer x, Consumer y) {x.andThen(y).accept(fraction); } }输出结果:
    【Java8新特性探索之函数式接口】50584.16666666666667
    由于Consumer的default方法所带来的嵌套调用(连锁调用) , 对行为的抽象的函数式编程理念 , 展示的淋漓尽致 。
    其他的消费型函数式接口汇总说明:
    接口名称方法名称方法签名DoubleConsumeraccept(double) -> voidIntConsumeraccept(int) -> voidLongConsumeraccept(long) -> voidObjDoubleConsumeraccept(T, double) -> voidObjIntConsumeraccept(T, int) -> voidObjLongConsumeraccept(T, long) -> void
    供给型接口Supplier
    java.util.function.Supplier 接口仅包含一个无参的方法: T get(), 用来获取一个泛型参数指定类型的对象数据 。
    接口源码:
    package java.util.function;@FunctionalInterfacepublic interface Supplier {T get();}由于这是一个函数式接口 , 意味着对应的Lambda表达式需要对外提供一个符合泛型类型的对象数据 。
    public class SupplierTest { public int getMax(Supplier supplier) {return supplier.get(); }/*** 获取数组元素最大值*/ @Test public void getMaxTest() {Integer[] data = http://kandian.youth.cn/index/new Integer[] { 5, 4, 6, 3, 2, 1 };int result = getMax(() -> {int max = 0;for (int i = 0; i < data.length; i++) {max = Math.max(max, data[i]);}return max;});System.out.println(result); } }其他的供给型函数式接口汇总说明:
    接口名称方法名称方法签名BooleanSuppliergetAsBoolean() -> booleanDoubleSuppliergetAsDouble() -> doubleIntSuppliergetAsInt() -> intLongSuppliergetAsLong() -> long
    函数型接口Function
    java.util.function.Function 接口用来根据一个类型的数据得到另一个类型的数据 , 前者称为前置条件 , 后者称为后置条件 。
    接口源码:
    package java.util.function;import java.util.Objects;@FunctionalInterfacepublic interface Function {R apply(T t);default Function compose(Function before) {Objects.requireNonNull(before);return (V v) -> apply(before.apply(v));}default Function andThen(Function after) {Objects.requireNonNull(after);return (T t) -> after.apply(apply(t));}staticFunction identity() {return t -> t;}}
    1. 抽象方法 apply(T t):该方法接收入参是一个泛型T对象 , 并返回一个泛型T对象 。 默认方法andThen(Function after):该方法接受一个行为 , 并将父方法处理过的结果作为参数再处理 。 compose(Function before):该方法正好与andThen相反 , 它是先自己处理然后将结果作为参数传给父方法执行 。 @Testpublic void andThenAndComposeTest() { // 计算公式相同 Function andThen1 = x -> x + 1; Function andThen2 = x -> x * 2; Function compose1 = y -> y + 1; Function compose2 = y -> y * 2; // 注意调用的先后顺序 // 传入参数2后 , 先执行andThen1计算 , 将结果再传入andThen2计算 System.out.println(andThen1.andThen(andThen2).apply(2)); // 传入参数2后 , 先执行compose2计算 , 将结果再传入compose1计算 System.out.println(compose1.compose(compose2).apply(2));}输出结果:65
    2. 静态方法identity():获取到一个输入参数和返回结果一样的Function实例 。
    来一个自驾九寨沟的代码示例:
    public class FunctionTest {@Test public void findByFunctionTest() {Function getMoney = m -> m.add(new BigDecimal(1000));BigDecimal totalCost = getMoney.apply(new BigDecimal(500));System.out.println("张三的钱包原本只有500元 , 自驾川西得去银行再取1000元 , 取钱后张三钱包总共有" +Function.identity().apply(totalCost) + "元");BigDecimal surplus = cost(totalCost, (m) -> {System.out.println("第二天出发前发现油不足 , 加油前有" + m + "元");BigDecimal lubricate = m.subtract(new BigDecimal(300));System.out.println("加油300后还剩余" + lubricate + "元");return lubricate;}, (m) -> {System.out.println("到达景区门口 , 买景区票前有" + m + "元");BigDecimal tickets = m.subtract(new BigDecimal(290));System.out.println("买景区票290后还剩余" + tickets + "元");return tickets;});System.out.println("最后张三返程到家还剩余" + surplus + "元"); } public BigDecimal cost(BigDecimal money, Function lubricateCost,Function ticketsCost) {Function firstNight = (m) -> {System.out.println("第一晚在成都住宿前有" + m + "元");BigDecimal first = m.subtract(new BigDecimal(200));System.out.println("交完200住宿费还剩余" + first + "元");return first;};Function secondNight = (m) -> {System.out.println("第二晚在九寨县住宿前有" + m + "元");BigDecimal second = m.subtract(new BigDecimal(200));System.out.println("交完200住宿费还剩余" + second + "元");return second;};return lubricateCost.andThen(ticketsCost).andThen(secondNight).compose(firstNight).apply(money); }}