1. 程式人生 > 其它 >函式式介面詳解

函式式介面詳解

函式式介面

以前一直好奇java能不能傳參的時候引數為方法,現在通過函式式介面可以做到了。以前一直用的不多,最近用到了就做一個簡單的彙總以及演示demo。

1.什麼是函式式介面?

  • 只包含一個抽象方法的介面,稱為函式式介面
  • 你可以通過Lambda表示式來建立該介面的物件。(若Lambda表示式丟擲一個受檢異常,那麼該異常需要在目標介面的抽象方法上進行宣告)
  • 我們可以在任意函式式介面上使用@FunctionalInterface註解,這樣做可以檢查它是否是一個函式式介面,同時javadoc也會包含一條宣告,說明這個介面是一個函式式介面

2.自定義函式

package function;

/**
 * @Description todo
 * @Author cz
 * @Date 2022/3/4
 */
public class Function {


    @FunctionalInterface
    public interface Func<T> {
        T get();
    }

    public static class FuncImpl implements Func<Integer> {

        @Override
        public Integer get() {
            return 3;
        }
    }

    public static Integer getInteger(Func<Integer> func) {
        return func.get();
    }

    public static void testFunc(){
        //匿名內部類的方式
        System.out.println(getInteger(new Func<Integer>() {

            @Override
            public Integer get() {
                return 3;
            }
        }));
        //Lambda形式
        System.out.println(getInteger(() -> 3));
        //實現類的方式
        System.out.println(getInteger(new FuncImpl()));
    }

    public static void main(String[] args) {
        //測試Function
        testFunc();
    }
}

3.JAVA內建四大核心函式式介面

在學習lambda表示式的時候,我們知道,要使用lambda表示式,我們就要建立一個函式式介面,那每次用lambda表示式的時候豈不是很麻煩,這時候,java給我們內建了四大核心函式式介面。

函式式介面 引數型別 返回型別 用途
Consumer 消費型介面 T 對型別為T的物件應用操作,包含方法:void accept(T t)
Supplier 共給型介面 返回型別為T的物件,包含方法:T get()
Function<T, R> 函式型介面 T R 對型別為T的物件應用操作,並返回結果,結果是R型別的物件,包含方法:R apply(T t)
Predicate 斷定型介面 T 確定型別為T的物件是否滿足某約束,並返回boolean值。包含方法boolean test(T t)

還有一些其他介面可看參照裡面的官方jdk文件裡面,或是直接看 java.util.function 包下面的介面

4.四大介面示例

4.1 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); };
    }
}

void accept(T t)

 public static class ConsumerAcceptImpl implements Consumer<String> {

        @Override
        public void accept(String s) {
            System.out.println(s);
        }
    }

    public static void testConsumerAccept(String name, Consumer<String> consumer){
        //do something with name
        //then consumer the name
        String helloName = String.format("hello %s", name);
        consumer.accept(helloName);
    }

    public static void testAcceptMain(){
        //lambda表示式
        testConsumerAccept("張三", System.out::println);
        //Consumer的實現類
        testConsumerAccept("張三", new ConsumerAcceptImpl());
        //匿名內部類
        testConsumerAccept("張三", new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
    }

Consumer andThen(Consumer<? super T> after)

 public static void testConsumerAndThen() {
        Consumer<Student> c1 = (Student s) -> System.out.printf("%s:%s%n","c1", s.getSchool());
        Consumer<Person> c2 = (Person p) -> System.out.printf("%s:%s%n", "c2", p.getName());
        Consumer<Student> c3 = c1.andThen(c2);

        Student s = new Student("s1的school", new Person("p", 11));
        s.setName("student父類person的屬性name");
        c3.accept(s);
    }

				/*  執行結果
        c1:s1的school
        c2:student父類person的屬性name

        返回一個 consumer 的accept 為 先執行c1的accept然後執行c2的accept
        */

4.2 Supplier:共給型介面

@FunctionalInterface
public interface Supplier<T> {

    T get();
}

T get( )

		//需求:產生指定個數的整數,並放入集合中
    public static List<Integer> getNumList(int num, Supplier<Integer> sup){
        List<Integer> list = new ArrayList<>();
        for(int i=0;i<num;i++) {

            Integer n = sup.get();
            list.add(n);

        }
        return list;
    }

    public static void testSupplierGet() {
        List<Integer> numList = getNumList(10, ()->(int)(Math.random()*100 ));
        for (Integer integer : numList) {
            System.out.println(integer);
        }
    }

4.3 Function<T,R>:函式型介面


@FunctionalInterface
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;
    }
}

R apply(T t)

		//需求:用於處理字串
    public  static String strHandler(String str, Function<String,String> fun) {
        System.out.println("這裡先處理,然後交給fun處理,這裡的處理算是strHandler處理的。");
        return fun.apply(str);
    }

    /*
    對型別為T的物件應用操作返回型別為R的物件
     */
    public static void  testFunctionApply() {
        String trimStr=strHandler("\t\t你好,world     ",(str) -> {
            System.out.println("這裡算是fun處理的,需要返回值");
            return str.trim();
        });
        System.out.println(trimStr);
    }

Function<T,V> compose(Function<? super V, ? extends T> before)

  public static void testFunctionCompose(){
        Function<String, String> before = String::trim; //對入參的String進行trim操作,返回trim以後的String;
        Function<String, String> f2 = str -> str.replace("hello", "你好"); //對入參的String裡面的hello替換為你好
        String rt = f2.compose(before).apply("hello, world    ");
        System.out.println(rt);
        /* 此處compose的作用其實就是將多個Function的apply方法連線在一起用,compose裡面的將Function的apply方法將提前於它的呼叫的那個
        Function的apply方法。看成是過濾器會很好理解。
        上述執行過程是 compose返回的Function f3.apply(f2.apply(before.apply(str)))
         */
    }

Function<T, V> andThen(Function<? super R, ? extends V> after)

 public static void testFunctionAndThen(){
        Function<String, String> after = String::trim; //對入參的String進行trim操作,返回trim以後的String;
        Function<String, String> f2 = str -> str.replace("hello", "你好"); //對入參的String裡面的hello替換為你好
        String rt = f2.andThen(after).apply("hello, world    ");
        System.out.println(rt);
        /* 此處compose的作用其實就是將多個Function的apply方法連線在一起用,andThen裡面的將Function的apply方法將後於它的呼叫的那個
        Function的apply方法。看成是過濾器會很好理解。
        上述執行過程是 andThen返回的Function f3.apply(after.apply(f2.apply(str)))
         */
    }

Function<T, T> identity()

 		/* 測試 Function<T, T> identity() 用法 
 		identity()返回的是一個入參和出參相同的Function*/
    public static void printString(String str, Function<String, String> f1){
        System.out.println(f1.apply(str));
    }

    public static void testFunctionIdentity(){
        printString("s1", Function.identity());
    }

4.4 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);
    }

    @SuppressWarnings("unchecked")
    static <T> Predicate<T> not(Predicate<? super T> target) {
        Objects.requireNonNull(target);
        return (Predicate<T>)target.negate();
    }
}

boolean test(T t) 用來處理引數T,看是否滿足要求,可以理解為 條件A

  public static void testPredicateTest(){
        Predicate<Integer> predicateTest = x -> x > 0;
        System.out.println(predicateTest.test(10));
    }
//true

Predicate and(Predicate<? super T> other) 返回一個Predicate, 同時滿足this.test(T t)和other.test(T t)

public static void testPredicateAnd(){
        Predicate<Integer> predicate = x -> x > 0;
        Predicate<Integer> other = x -> x < 10;
        System.out.println(predicate.and(other).test(11));
    }
//flase

Predicate negate() 返回一個Predicate,且與之前 this.test()取反

 public static void testPredicateNegate(){
        Predicate<Integer> predicate = x -> x > 0;
        System.out.println(predicate.negate().test(10));
    }
 //false

Predicate or(Predicate<? super T> other) this.test()||other.test()

 public static void testPredicateOr(){
        Predicate<Integer> predicate = x -> x > 0;
        Predicate<Integer> other = x -> x < 0;
        predicate.or(other).test(0);
    }
    //false

Predicate isEqual(Object targetRef) 判斷引用是否相等

 public static void testPredicateIsEqual(){
        Object obj = new Object();
        Predicate.isEqual(obj).test(obj);
    }
//true

Predicate not(Predicate<? super T> target) target.test()取反

public static void testPredicateNot(){
        Predicate<Integer> p1 = x -> x>0;
        System.out.println(Predicate.not(p1).test(-1));
    }
//true

5. 其他與Predicate相關的介面

  • BiPredicate<T, U>

    針對兩個引數,看兩個引數是否符合某個條件表示式

  • DoublePredicate

    看一個double型別的值是否符合某個條件表示式

  • IntPredicate

    看一個int型別的值是否符合某個條件表示式

  • LongPredicate

    看一個long型別的值是否符合某個條件表示式

參考:
1.https://www.jianshu.com/p/8005f32caf3d
2.https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/function/package-summary.html
3.https://www.jianshu.com/p/b38ff80e3039
4.原始碼地址:https://gitee.com/ashscc/java-ptn/tree/master/baseJDK/src/main/java/function

本文來自部落格園,作者:orangeScc,轉載請註明原文連結:https://www.cnblogs.com/ashScc/p/15972683.html