1. 程式人生 > 實用技巧 >三、函式式介面

三、函式式介面

自定義函式式介面

  • Lambda表示式需要函式式介面的支援
  • 函式式介面定義:介面中只有一個抽象方法的介面,稱為函式式介面。
  • 可以使用註解 @FuncitonalInterface 修飾,其修飾作用為:限定該介面必須為函式式介面,即該介面中有且只有一個抽象方法。否則無法通過編譯。即可以檢查是否為函式式介面。

實現

    /**
     * 自定義函式介面
     * @param <T>
     * @param <R>
     */
    @FunctionalInterface
    public interface Operation<T,R> {
        R operation(T t1, T t2);
    }
    /**
     * 具體實現方法
     * @param l1
     * @param l2
     * @param operation
     */
    public void op (Long l1, Long l2, Operation<Long,Long> operation){
        System.out.println(operation.operation(l1,l2));
    }

測試

   /**
     * 寫具體實現方法再直接使用
     */
    @Test
    public void testOperation1(){
        GoodsService goodsService = new GoodsService();
        goodsService.op(10l,10l,(x,y) -> x*y);
        goodsService.op(100l,200l,(x,y)-> x+y);
    }

    /**
     * 先使用lambda表示具體實現方法體,再進行介面中的方法呼叫,傳入具體值
     */
    @Test
    public void testOperation2(){
        Operation<Integer,Integer>  op = (x,y) -> x*y;
        System.out.println(op.operation(10,10));
    }

實際使用時,大多數情況下直接使用Java8內建四大函式式介面,並不要進行自己寫函式式介面。

Java內建的四大核心函式式介面

  1. Consumer 消費型介面 消費物件
    • void accept(T t);
  2. Supplier 供給型介面 生成物件
    • T get();
  3. Function<R,T> 函式型介面 指定特定功能
    • R apply(T t);
  4. Predicate 斷言型介面 進行條件判斷
    • boolean test(T t);

案例

   /**
     * Consumer<T> 消費型介面
     * void accept(T t);
     *
     * @param n
     * @param con
     */
    public void consume(Integer n , Consumer<Integer> con){
        con.accept(n);
    }

    /**
     * Supplier<T> 供給型介面
     * T get();小括號無引數
     *
     * 呼叫此方法時,第二個引數提供一個數字集合
     * @param n
     * @param sup
     * @return
     */
    public List<Integer> getNumList(int n, Supplier<Integer> sup){
        List<Integer> numList = new ArrayList<>();

        for (int i = 0; i < n; i++){
            numList.add(sup.get()); //通過get方法得到數字 存到numList
        }
        return numList;
    }

    /**
     * Function<R,T> 函式型介面 指定特定功能
     * 定義一個處理字串功能型介面函式
     * @param str
     * @param fun
     * @return
     */
    public  String strHandler(String str, Function<String,String> fun){
        return fun.apply(str);
    }

    /**
     * Predicate<T> 條件判斷
     * boolean test(T t); 返回boolean
     * 使用斷言型介面過濾字串
     * @param strs
     * @param pred
     * @return
     */
    public List<String> strFilter(List<String> strs, Predicate<String> pred){
        List<String>  list = new ArrayList<>();
        for (String s:strs
        ) {
            //利用斷言型介面進行指定功能判斷  即一個功能性條件判斷
            if(pred.test(s)){
                //過濾功能
                list.add(s);
            }
        }
        return list;
    }

測試

    @Test
    public void testConsumer(){
        FunctionInterface functionInterface = new FunctionInterface();
        //此時的(d) 小括號裡有引數
        //原因是因為 Consumer介面有引數
        functionInterface.consume(1000,(d)-> System.out.println(d));
    }

    @Test
    public void testSupplier(){
        FunctionInterface functionInterface = new FunctionInterface();
        //T get(); 小括號無引數
        List<Integer> numList = functionInterface.getNumList(10,() -> (int)(Math.random()*101));
        for ( Integer i: numList
        ) {
            System.out.println(i);
        }
    }
    @Test
    public void testFunction(){
        FunctionInterface functionInterface = new FunctionInterface();
        //將字串轉成大寫
        String str1 = functionInterface.strHandler("ghslkajh", (s) -> s.toUpperCase());
        System.out.println(str1);
    }
    @Test
    public void testPredicate(){
        FunctionInterface functionInterface = new FunctionInterface();
        //返回長度大於3的字串
        List<String> s1 = functionInterface.strFilter(Arrays.asList("huzhiqi", "adaad", "1231", "414441", "gagsgasg"), (s) -> s.length() > 3);
        System.out.println(s1); //[huzhiqi, adaad, 1231, 414441, gagsgasg]
        //返回包含d的字串
        List<String> s2 = functionInterface.strFilter(Arrays.asList("huzhiqi", "adaad", "1231", "414441", "gagsgasg"), (s) -> s.contains("d"));
        System.out.println(s2); // [adaad]
    }