Jdk8新特性三:jdk8之函數式編程Function

Jdk8新特性三:jdk8之函數式編程Function

Function接口的使用

  1. Lambda表達式必須先定義接口,創建相關方法後才能使用,這樣弄十分不便,乾脆開發者就直接內置了接口,所有標註@FunctionalInterface註解的接口都是函數式接口。
  2. jdk8內置的四大核心函數式接口

Consumer:消費型接口,有入參,無返回值。

​ void accept(T t);

Supplier:供給型接口:無入參,有返回值

​ T get();

Function<T,R>:函數型接口,有入參,有返回值

​ R apply(T t);

Predicate:斷言型接口,有入參,有返回值,返回值類型確定是boolean

​ boolean test(T,t);

  1. Function<T,R>:傳入一個值,經過函數的計算返回另一個值(T,入參類型,R:出參類型)
//這個就相當於聲明瞭一個函數變量,和js很像,然後調用這個函數。之所以能這樣寫是因爲
Function<Integer,Integer> func=p->{
    System.out.println("我是函數");
    return p*100;
};
func.apply(5);
  1. 如果用lambda表達式可以這樣寫
//也可以這樣寫,定義了一個函數的行爲。p->p*12,因爲Function本身就是一個函數式編程,可以將函數作爲參數進行傳遞。
Function<Integer,Integer> func2=p->p*12;
System.out.println(func2.apply(5));

BiFunction接口解決傳入兩個參數問題

  1. 可以通過Ctrl+Shift+n查找BiFunction類。可以看到也是函數式編程。可以傳入兩個參數。用法和上面一個參數的一樣。
System.out.println(opreator(1,2,(a,b)->a+b));
System.out.println(opreator(1,2,(a,b)->a*b));
BiFunction<Integer,Integer,Integer> bin=(a,b)->a+b;
System.out.println(bin.apply(5,10));
BiFunction<Integer,Integer,Integer> bin2=(a,b)->{
    System.out.println("我是bin2");
    return a*b;
};
System.out.println(bin2.apply(5,10));
public static Integer opreator(Integer a, Integer b, BiFunction<Integer,Integer,Integer> bf){
    return bf.apply(a,b);
}

JDK8函數式編程消費型接口Consumer<T>

  1. Consumer<T> 有入參,無返回值。idea中可以通過ctrl+shift+n輸入Consumer.java找到源代碼。沒有返回值主要的應用場景打印日誌,發送短信
    Consumer<String> consumer=obj->{
        //這裏面可以寫很多邏輯
        System.out.println(obj);
        System.out.println("調用短信接口發送短信,或者打印日誌");
    };
    //consumer.accept("88888");
    sendMsg("88888",consumer);
    List<String> list= Arrays.asList("aaa","bbb","ccc");
    list.forEach(obj->{ 
        System.out.println(obj);
	});
public static void sendMsg(String phone,Consumer<String> consumer){
    consumer.accept(phone);//consumer代表一個函數,phone是接收的參數。accept()方法表示這個函數運行這個參數。類似於開啓新線程中的start()
}

Jdk8函數式編程供給型接口Supplier

  1. Supplier是供給型接口,無入參,有返回值 。也就是沒有入參。
  2. 運用場景:如果項目中你需要一些實體類需要有默認值,而有些地方不需要默認值,我們如何處理呢?我們可以設計一個工廠模式,工廠對實體類生產兩種產品,一個有默認值,一個沒有默認值。
public static Student newStudent(){
    Supplier<Student> supplier=()->{
        Student student=new Student();
        student.setName("默認名稱");
        return student;
    };
    return supplier.get();
}
  1. 這樣我們只需要實例化這個newStudent就可以了。注意裏面寫的lambda表達式。是定義一個supplier的函數,然後在結尾supplier.get()方法進行調用,自己調用自己。
Student student=newStudent();
System.out.println(student.getName());

Jdk8函數式編程之斷言型接口:Predicate

  1. Predicate:斷言型接口,有入參,有返回值,返回值類型確定是boolean.T爲入參類型,出參類型爲Boolean
  2. 用途:接收一個參數,用於判斷是否滿足一定的條件,過濾數據。
public static List<String> filter(List<String> list,Predicate<String> predicate){
    List<String> results=new ArrayList<>();
    for(String str:list){
        if(predicate.test(str)){
            results.add(str);
        }
    }
    return results;
}
  1. 調用函數
List<String> list=Arrays.asList("difjisfj","343dfjsj","kfjsidj","34dfjs","djfsi");
System.out.println(list);
List<String> a = filter(list, (obj) -> obj.startsWith("a"));
List<String> filter2 = filter(list, (obj) -> {
    return obj.startsWith("3");
});
System.out.println(a);

Jdk8方法與構造函數的引用

  1. 之前調用方法操作:對象.方法,類名.方法。前面是實例方法,後面是靜態方法。
  2. jdk8提供了另外一種調用方式,雙冒號 ::

​ 這種調用方式,用來直接訪問類和實例已經存在的方法或構造方法。可以通過方法引用,賦值給另外一個變量。

語法:

​ 左邊是容器(或者類名,方法名),中間是"::",右邊是相應的方法名

**靜態方法:**則是ClassName::methodName

**實例方法:**則是(對象)Instance::methodName

**構造函數:**則是類名::new;

Lambda表達式的使用:

​ Function<入參1,返回類型> func= 方法引用

​ 應用:func.apply(入參);

​ BiFunction<入參1,入參2,返回類型> func=方法引用

​ 應用:func.apply(入參1,入參2);

  1. 引用靜態方法作爲函數傳遞
Function<String,Integer> fun =Integer::parseInt;
Integer apply = fun.apply("1204");
System.out.println(apply);
  1. 引用非靜態方法作爲函數傳遞
//使用雙冒號::來構造非靜態函數的引用
String text="你好啊!美女";
Function<Integer,String> func2=text::substring;
String apply1 = func2.apply(1);
System.out.println(apply1);
  1. 引用構造函數作爲函數傳遞,含多個參數和單個參數,主要是通過Function<>裏面的參數來識別調用的是哪個構造函數。
class User{
    private String name;
    private int age;

    public User() {
    }

    public User(String name) {
        this.name = name;
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
    }
}
//構造函數引用,多個參數
BiFunction<String,Integer,User> biFunction=User::new;
User user2 = biFunction.apply("張三", 1);
System.out.println(user2);

Function<String,User> funct2=User::new;
User user3 = funct2.apply("張三");
System.out.println(user3);
  1. 可以作爲一個函數聲明,也可以將函數做爲參數傳遞過去
sayHello(String::toUpperCase,"abcdefg");

public static void sayHello(Function<String,String> func,String paramer){
    String result = func.apply(paramer);
    System.out.println(result);
}
發佈了216 篇原創文章 · 獲贊 202 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章