Java8-FunctionalInterface

Java8-函數式接口

yann-allegre-L-fsASSJ29c-unsplash.jpg

函數式接口

概念

一、有且只有一個抽象方法的接口java

二、函數式接口,即適用於函數式編程場景的接口。
Java中的函數式編程體現就是Lambda,因此函數式接口就是能夠適用於Lambda使用的接口。
只有確保接口中有且僅有一個抽象方法,Java中的Lambda才能順利地進行推導。編程

格式

public interface InterfaceName {
    public abstract 返回值類型 方法名稱(可選參數信息);
    // 其餘非抽象方法內容
}

public interface MyFunctionalInterface {
    void myMethod();
}

註解

@FunctionalInterface
public interface MyFunctionalInterface {
    void myMethod();
}

一旦使用該註解來定義接口,編譯器將會強制檢查該接口是否確實有且僅有一個抽象方法,不然將會報錯。
須要注意的是,即便不使用該註解,只要知足函數式接口的定義,這仍然是一個函數式接口,使用起來都同樣。數組

四大經常使用函數式接口

SupplierConsumerPredicateFunctionapp

Supplier接口

@FunctionalInterface
public interface Supplier<T> {
    T get();
}
/**
* Supplier 供給型接口 沒有參數,只有返回值
*/
public class Demo04 {
    public static void main(String[] args) {
//      Supplier supplier = new Supplier<Integer>() {
//          @Override
//          public Integer get() {
//              System.out.println("get()");
//              return 1024;
//          }          
//      };
        Supplier supplier = ()->{ return 1024; };
        System.out.println(supplier.get());
    }
}

抽象方法:getide

/**
 * 經常使用的函數式接口
 *     java.util.function.Supplier<T>接口僅包含一個無參的方法:T get()。
 *     用來獲取一個泛型參數指定類型的對象數據。
 *
 *     Supplier<T>接口被稱之爲生產型接口,指定接口的泛型是什麼類型
 *     那麼接口中的get方法就會生產什麼類型的數據
 */
public class SupplierDemo01 {
    //定義一個方法,方法的參數傳遞Supplier<T>接口,泛型執行String,get方法就會返回一個String
    public static String getString(Supplier<String> sup){
        return sup.get();
    }
    public static void main(String[] args) {
        String string = getString(() -> {
            return "胡歌";
        });
        System.out.println(string);

        //優化Lambda表達式
        String s2 = getString(()->"胡歌");
        System.out.println(s2);
    }
}

/**
 * 練習:求數組元素最大值
 *         使用Supplier接口做爲方法參數類型,經過Lambda表達式求出int數組中的最大值。
 *         提示:接口的泛型請使用java.lang.Integer類。
 */
public class TestDemo02 {
    public static int getMax(Supplier<Integer> supplier){
        return supplier.get();
    }
    public static void main(String[] args) {
        //定義一個int類型的數組,並賦值
        int[] arr = {100,0,-50,880,99,33,-30};
        //調用getMax方法,方法的參數Supplier是一個函數式接口,因此能夠傳遞Lambda表達式
        int maxValue = getMax(()->{
            //獲取數組的最大值,並返回
            //定義一個變量,把數組中的第一個元素賦值給該變量,記錄數組中元素的最大值
            int max = arr[0];
            //遍歷數組,獲取數組中的其餘元素
            for (int i : arr) {
                //使用其餘的元素和最大值比較
                if (i>max)
                    max = i;
                    //若是i大於max,則替換max做爲最大值
            }
            return max;
        });
        System.out.println(maxValue);
    }
}

Consumer接口

消費性接口函數式編程

@FunctionalInterface
//                  只有輸入,沒有返回值
public interface Consumer<T> {
    
    void accept(T t);
    
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}
/**
* Consumer 消費型接口: 只有輸入,沒有返回值
*/
public class Demo03 {
    public static void main(String[] args) {
//      Consumer<String> consumer = new Consumer<String>() {
//          @Override
//          public void accept(String str) {
//              System.out.println(str);
//              }       
//          };
        Consumer<String> consumer = (str)->{System.out.println(str);};
        consumer.accept("sdadasd");
    }
}

抽象方法:accept函數

消費一個指定泛型的數據優化

/**
 * java.util.function.Consumer<T>接口則正好與Supplier接口相反,
 *         它不是生產一個數據,而是消費一個數據,其數據類型由泛型決定。
 *     Consumer接口中包含抽象方法void accept(T t),意爲消費一個指定泛型的數據。
 *
 *    Consumer接口是一個消費型接口,泛型執行什麼類型,就可使用accept方法消費什麼類型的數據
 *    至於具體怎麼消費(使用),須要自定義(輸出,計算....)
 */
public class ConsumerDemo01 {

    public static void method(String name, Consumer<String> consumer){
        consumer.accept(name);
    }
    public static void main(String[] args) {

        //Consumer<String> consumer = (str)->{System.out.println(str);};
        //consumer.accept("sdadasd");
        //accept中的name值"趙麗穎"賦值給了下面的name
        method("趙麗穎",(String name)->{
            //對傳遞的字符串進行消費
            //消費方式:直接輸出字符串
            System.out.println(name);

            //消費方式:把字符串進行反轉輸出
            String reName = new StringBuffer(name).reverse().toString();
            System.out.println(reName);
        });
    }
}

默認方法:andThenui

"一步接一步」操做spa

/**
 * Consumer接口的默認方法andThen
 *    做用:須要兩個Consumer接口,能夠把兩個Consumer接口組合到一塊兒,在對數據進行消費
 *
 *    例如:
 *     Consumer<String> con1
 *     Consumer<String> con2
 *     String s = "hello";
 *     con1.accept(s);
 *     con2.accept(s);
 *     鏈接兩個Consumer接口  再進行消費
 *     con1.andThen(con2).accept(s); 誰寫前邊誰先消費
 */
public class ConsumerAndThenDemo02 {

    //定義一個方法,方法的參數傳遞一個字符串和兩個Consumer接口,Consumer接口的泛型使用字符串
    public static void method(String s, Consumer<String> con1,Consumer<String> con2){
        //con1.accept(s);
        //con2.accept(s);
        //使用andThen方法,把兩個Consumer接口鏈接到一塊兒,在消費數據
        //con1鏈接con2,先執行con1消費數據,在執行con2消費數據
        con1.andThen(con2).accept(s);
    }
    public static void main(String[] args) {
        method("Hello",(t)->{
            System.out.println(t.toUpperCase());
        },(t)->{
            System.out.println(t.toLowerCase());
        });

    }
}

Predicate接口

斷言型接口:有一個輸入參數,返回值只能是布爾值

@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);

    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }
    
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}
/**
* 判定型接口:有一個輸入參數,返回值只能是 布爾值!
*/
public class Demo02 {
    public static void main(String[] args) {
        //判斷字符串是否爲空
//      Predicate<String> predicate = new Predicate<String>(){
//      @Override
//          public boolean test(String str) {
//              return str.isEmpty();
//          }
//      };
        Predicate<String> predicate = (str)->{return str.isEmpty(); };
        System.out.println(predicate.test(""));
    }
}

抽象方法:test

用於條件判斷的場景

/**
 * java.util.function.Predicate<T>接口
 *     做用:對某種數據類型的數據進行判斷,結果返回一個boolean值
 *
 *     Predicate接口中包含一個抽象方法:
 *         boolean test(T t):用來對指定數據類型數據進行判斷的方法
 *             結果:
 *                 符合條件,返回true
 *                 不符合條件,返回false
 */
public class PredicateDemo01 {
    /*
       定義一個方法
       參數傳遞一個String類型的字符串
       傳遞一個Predicate接口,泛型使用String
       使用Predicate中的方法test對字符串進行判斷,並把判斷的結果返回
    */
    public static boolean checkString(String s, Predicate<String> pre){
        return  pre.test(s);
    }
    public static void main(String[] args) {
        //定義一個字符串
        String s = "abcdef";

        //調用checkString方法對字符串進行校驗,參數傳遞字符串和Lambda表達式
        /*boolean b = checkString(s,(String str)->{
            //對參數傳遞的字符串進行判斷,判斷字符串的長度是否大於5,並把判斷的結果返回
            return str.length()>5;
        });*/

        //優化Lambda表達式
        boolean b = checkString(s,str->str.length()>5);
        System.out.println(b);
    }
}

默認方法:and

邏輯並。兩個條件同時知足返回true

/**
 *     需求:判斷一個字符串,有兩個判斷的條件
 *         1.判斷字符串的長度是否大於5
 *         2.判斷字符串中是否包含a
 *     兩個條件必須同時知足,咱們就可使用&&運算符鏈接兩個條件
 */
public class PredicateAndDemo02 {
    public static boolean checkString(String s, Predicate<String> pre1,Predicate<String> pre2){
        //等價於return pre1.test(s) && pre2.test(s);
        return pre1.and(pre2).test(s);
    }
    public static void main(String[] args) {
        //定義一個字符串
        String s = "abcdef";
        //調用checkString方法,參數傳遞字符串和兩個Lambda表達式
        boolean b = checkString(s,(String str)->{
            //判斷字符串的長度是否大於5
            return str.length()>5;
        },(String str)->{
            //判斷字符串中是否包含a
            return str.contains("a");
        });
        System.out.println(b);

    }
}

默認方法:or

邏輯或,兩個條件知足一個返回true

/**
 * 需求:判斷一個字符串,有兩個判斷的條件
 *  1.判斷字符串的長度是否大於5
 *   2.判斷字符串中是否包含a
 *  知足一個條件便可,咱們就可使用||運算符鏈接兩個條件
 *
 */
public class PredicateOrDemo03 {
    /*
            定義一個方法,方法的參數,傳遞一個字符串
            傳遞兩個Predicate接口
                一個用於判斷字符串的長度是否大於5
                一個用於判斷字符串中是否包含a
                知足一個條件便可
         */
    public static boolean checkString(String s, Predicate<String> pre1, Predicate<String> pre2){
        //return pre1.test(s) || pre2.test(s);
        return  pre1.or(pre2).test(s);//等價於return pre1.test(s) || pre2.test(s);
    }
    public static void main(String[] args) {
        //定義一個字符串
        String s = "bc";
        //調用checkString方法,參數傳遞字符串和兩個Lambda表達式
        boolean b = checkString(s,(String str)->{
            //判斷字符串的長度是否大於5
            return str.length()>5;
        },(String str)->{
            //判斷字符串中是否包含a
            return str.contains("b");
        });
        System.out.println(b);
    }
}

默認方法:negate

結果取反

/**
 * 需求:判斷一個字符串長度是否大於5
 *         若是字符串的長度大於5,那返回false
 *         若是字符串的長度不大於5,那麼返回true
 *     因此咱們可使用取反符號!對判斷的結果進行取反
 */
public class PredicateNegateDemo04 {
    /**
     * 定義一個方法,方法的參數,傳遞一個字符串
     * 使用Predicate接口判斷字符串的長度是否大於5
    */
    public static boolean checkString(String s, Predicate<String> pre){
        //return !pre.test(s);
        return  pre.negate().test(s);//等效於return !pre.test(s);
    }
    public static void main(String[] args) {
        //定義一個字符串
        String s = "abc";
        //調用checkString方法,參數傳遞字符串和Lambda表達式
        boolean b = checkString(s,(String str)->{
            //判斷字符串的長度是否大於5,並返回結果
            return str.length()>5;
        });
        System.out.println(b);
    }
}

Function接口

@FunctionalInterface
//                T 傳入參數、R返回類型                     
public interface Function<T, R> {

    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

   
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}
/**
* Function 函數型接口, 有一個輸入參數,有一個輸出
* 只要是 函數型接口 能夠 用 lambda表達式簡化
*/

public class Demo01 {
    public static void main(String[] args) {
//      Function<String,String> function = new Function<String,String>() {
//         @Override
//         public String apply(String str) {
//           return str;   
//         }
//      };
        Function<String,String> function = (str)->{return str;};
        System.out.println(function.apply("asd"));
    }
}
/**
 *  java.util.function.Function<T,R>接口用來根據一個類型的數據獲得另外一個類型的數據,
 *         前者稱爲前置條件,後者稱爲後置條件。
 *     Function接口中最主要的抽象方法爲:R apply(T t),根據類型T的參數獲取類型R的結果。
 *         使用的場景例如:將String類型轉換爲Integer類型。
 */
public class FunctionDemo01 {
    /**
     * 定義一個方法
     * 方法的參數傳遞一個字符串類型的整數
     * 方法的參數傳遞一個Function接口,泛型使用<String,Integer>
     *     使用Function接口中的方法apply,把字符串類型的整數,轉換爲Integer類型的整數
    */
    public static void change(String s, Function<String,Integer> fun){
        //Integer in = fun.apply(s);
        int in = fun.apply(s);//自動拆箱 Integer->int
        System.out.println(in);
    }
    public static void main(String[] args) {
        //定義一個字符串類型的整數
        String s = "1234";
        //調用change方法,傳遞字符串類型的整數,和Lambda表達式
        change(s,(String str)->{
            //把字符串類型的整數,轉換爲Integer類型的整數返回
            return Integer.parseInt(str);
        });
        //優化Lambda
        change(s,str->Integer.parseInt(str));
    }
}

默認方法:andThen

組合操做

/**
 *  Function接口中的默認方法andThen:用來進行組合操做
 *
 *     需求:
 *         把String類型的"123",轉換爲Inteter類型,把轉換後的結果加10
 *         把增長以後的Integer類型的數據,轉換爲String類型
 *
 *     分析:
 *         轉換了兩次
 *         第一次是把String類型轉換爲了Integer類型
 *             因此咱們可使用Function<String,Integer> fun1
 *                 Integer i = fun1.apply("123")+10;
 *         第二次是把Integer類型轉換爲String類型
 *             因此咱們可使用Function<Integer,String> fun2
 *                 String s = fun2.apply(i);
 *         咱們可使用andThen方法,把兩次轉換組合在一塊兒使用
 *             String s = fun1.andThen(fun2).apply("123");
 *             fun1先調用apply方法,把字符串轉換爲Integer
 *             fun2再調用apply方法,把Integer轉換爲字符串
 */
public class FunctionAndThenDemo02 {
    /**
     *  定義一個方法
     *   參數串一個字符串類型的整數
     *   參數再傳遞兩個Function接口
     *       一個泛型使用Function<String,Integer>
     *       一個泛型使用Function<Integer,String>
     */
    public static void change(String s, Function<String,Integer> fun1, Function<Integer,String> fun2){
        String ss = fun1.andThen(fun2).apply(s);
        System.out.println(ss);
    }

    public static void main(String[] args) {
        //定義一個字符串類型的整數
        String s = "123";
        //調用change方法,傳遞字符串和兩個Lambda表達式
        change(s,(String str)->{
            //把字符串轉換爲整數+10
            return Integer.parseInt(str)+10;
        },(Integer i)->{
            //把整數轉換爲字符串
            return i+"";
        });

        //優化Lambda表達式
        change(s,str->Integer.parseInt(str)+10,i->i+"");
    }
}
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息