Java之函数式接口

函数式接口

概述:接口中只有一个抽象方法

下面介绍的可能很抽象,理解不了,至少在我看来单独的这几个借口是没有用的,跟最下面说的 Stream流一起用才会有效果

  • 函数式接口,即适用于函数式编程场景的接口。而Java中的函数式编程体现就是Lambda,所以函数式接口就是可
    以适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导。

    备注:“语法糖”是指使用更加方便,但是原理不变的代码语法。例如在遍历集合时使用的for-each语法,其实
    底层的实现原理仍然是迭代器,这便是“语法糖”。从应用层面来讲,Java中的Lambda可以被当做是匿名内部
    类的“语法糖”,但是二者在原理上是不同的。

  • 格式:

    1. 只要确保接口中有且仅有一个抽象方法即可:

       修饰符 interface 接口名称 {
          public abstract 返回值类型 方法名称(可选参数信息);
          // 其他非抽象方法内容
       }
      
    2. @FunctionalInterface注解

      与@Override 注解的作用类似,Java 8中专门为函数式接口引入了一个新的注解: @FunctionalInterface 。该注
      解可用于一个接口的定义上,一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。需要注
      意的是,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。

    3. 自定义函数式接口(前面已经写过,这就不重复写了)

      package com.wzlove.function;

      /**

      • 自定义函数式接口

      • 使用@FunctionalInterface可以说明该接口是函数式接口,但是不加,如果接口中只有一个抽象方法,这个接口也是函数式接口

      • 也就是说函数式接口不以注解的存在而存在
        */
        @FunctionalInterface
        public interface MyFunctionalInterface {

        public abstract void show();
        }

lambda表达式: (参数列表)->

lambda表达式(前面有篇文章说过,不详细说明)

有参数,有返回值的自定义函数式接口

    @FunctionalInterface
    public interface Sumable {
        int sum(int a, int b);
    }

JDK1.8之后的某些函数式接口

supplier生产数据函数式接口

目的是生产数据.

目前好像看不出来有什么用,但是好像和jdk8的Stream流有关.,举个小例子

    package com.wzlove.supplier;
    
    import java.util.function.Supplier;
    
    /**
     * 使用supplier函数式接口求数组的最大值
     */
    public class ArrMaxValue {
    
        public static int getMaxValue(Supplier<Integer> sup){
            return sup.get();
        }
    
        public static void main(String[] args) {
            // 创建数组
            int[] arr = {100,20,50,30,99,101,-50};
    
            int maxValue = getMaxValue(()->{
                int max = arr[0];
                for (int i : arr) {
                    if(i > max){
                        max = i;
                    }
                }
                return max;
            });
    
            System.out.println("数组中的最大值为:" + maxValue);
        }
    
    }

Consumer消费数据函数式接口

这个方法是用来消费数据的,如何消费,消费规则自己定义.

java.util.function.Supplier 接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对
象数据。由于这是一个函数式接口,这也就意味着对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象
数据。

package com.wzlove.comsumer;

import java.util.function.Consumer;

/**
 * 使用Consumer函数式接口实现格式化输出
 */
public class ConsumerDemo2 {

    public static void printInfo(String[] strArr, Consumer<String> con1, Consumer<String> con2){

        for (int i = 0; i < strArr.length; i++) {
            con1.andThen(con2).accept(strArr[i]);
        }

    }

    public static void main(String[] args) {
        String[] strArr = {"迪丽热巴,女","郑爽,女","杨紫,女"};
        printInfo(strArr,(message)->{
            System.out.print("姓名:" + message.split(",")[0] + "。  ");
        },(message)->{
            System.out.println("性别:" + message.split(",")[1] + "。");

        });
    }
}

Predicate判断函数式接口

Predicate 接口中包含一个抽象方法: boolean test(T t) 。用于条件判断的场景

默认方法:

  • default Predicate and(Predicate<? super T> other) : 将两个Predicate 条件使用“与”逻辑连接起来实现“并且”的效果

  • default Predicate or(Predicate<? super T> other) : or 实现逻辑关系中的“或”

  • default Predicate negate() : 取反

    package com.wzlove.functionalinterface.predicate;

    import java.util.ArrayList;
    import java.util.function.Predicate;

    /**
    *
    */
    public class PredicateDemo2 {

      /**
       * 检查数组中的元素是否符合要求,满足要求加入List中并返回
       * @param arr      需要判断的数组
       * @param pre1     判断接口1,判断性别是否为女
       * @param pre2     判断接口2,判断姓名长度是否大于2
       * @return         集合
       */
      public static ArrayList<String> checkStar(String[] arr, Predicate<String> pre1, Predicate<String> pre2){
          // 创建集合
          ArrayList<String> list = new ArrayList<>();
          for (String s : arr) {
             if( pre1.and(pre2).test(s)){
                 list.add(s);
             }
          }
          return list;
      }
    
      public static void main(String[] args) {
          // 创建数组
          String[] arr = {"迪丽热巴,女","杨洋,男","李溪芮,女","郑爽,女"};
    
          // 调用方法(Lambda表达式可以简化)
          ArrayList<String> list = checkStar(arr,(str)->{
              return str.split(",")[1].equals("女");
          },(str)->{
              return str.split(",")[0].length() > 2;
          });
    
          // 遍历集合
          for (String elem : list) {
              System.out.print(elem + "   ");
          }
      }
    

    }

Function类型转换函数式接口

Function 接口中最主要的抽象方法为: R apply(T t) ,根据类型T的参数获取类型R的结果。

Function 接口中有一个默认的andThen 方法,用来进行组合操作。

package com.wzlove.functionalinterface.function;

import java.util.function.Function;

/**
 *
 */
public class FunctionDemo2 {

    /**
     * 将String分割,获得第二个元素,将数据转化为int,int数据加100,再将int转化为String
     * @param str    转化的数据
     * @param fun1   String -> String
     * @param fun2   String -> Integer
     * @param fun3   Integer -> String
     * @return       最后的String
     */
    public static String convert(String str,
                              Function<String,String> fun1,
                              Function<String, Integer> fun2,
                              Function<Integer,String> fun3){

        return fun1.andThen(fun2).andThen(fun3).apply(str);

    }

    public static void main(String[] args) {
        String str = convert("迪丽热巴,23",(s)->{
            return s.split(",")[1];
        },(s)->{
            return Integer.parseInt(s) + 100;
        },(s)->{
            return String.valueOf(s);
        });
        System.out.println(str);
    }
}
posted @ 2018-07-29 11:01  庄子游世  阅读(15114)  评论(0编辑  收藏  举报