Java-Lambda

Lambda是什麼

Lambda 表達式,也可稱爲閉包,它是推動 Java 8 發佈的最重要新特性,Lambda 允許把函數作爲一個方法的參數(函數作爲參數傳遞進方法中),使用 Lambda 表達式可以使代碼變的更加簡潔緊湊。
Lambda是一個匿名函數

        ()->{}
        ():描述參數列表;{}:用來描述方法體
        ->:lambda運算符,稱作 goes to

函數式接口

說到Lambda就不得不說函數式接口
什麼是函數式接口?

  • 只包含一個抽象方法的接口,稱爲函數式接口。
  • 可以通過Lambda表達式來創建該接口的對象(若Lambda表達式拋出一個受檢異常,那麼該異常需要在目標接口的抽象方法上進行聲明)
  • 在Java8後可以在任意函數式接口上使用@FunctionalInterface註解,其主要用於編譯級錯誤檢查,加上該註解,當你寫的接口不符合函數式接口定義的時候,編譯器會報錯。
@FunctionalInterface
public interface LambdaNoneReturnMutipleParm {
    void test(int a,int b);
}

Lambda的使用條件

從以上能夠看出,Lambda的使用條件是接口中有且只有一個必須實現的方法,如果有一個以上,Lambda就不知道該實現那個方法,在java8中新增了接口的默認方法,Lambda不受其影響
在這裏插入圖片描述
默認方法:

@FunctionalInterface
public interface LambdaNoneReturnMutipleParm {
    void test(int a,int b);
    default void test(){
        System.out.println("默認方法");
    }
}

Lambda的使用

先創建六個接口來分別測試

@FunctionalInterface
public interface LambdaNoneReturnMutipleParm {
    void test(int a,int b);
    default void test(){
        System.out.println("默認方法");
    }
}
-----
@FunctionalInterface
public interface LambdaNoneReturnNoneParm {
    void test();
}
-----
@FunctionalInterface
public interface LambdaNoneReturnSingleParm {
    void test(int a);
}
-----
@FunctionalInterface
public interface LambdaSingleReturnMutipleParm {
    int test(int a,int b);
}
-----
@FunctionalInterface
public interface LambdaSingleReturnNoneParm {
    int test();
}
-----
@FunctionalInterface
public interface LambdaSingleReturnSingleParm {
    int test(int a);
}

Lambda表達式的基礎語法

 //1.Lambda表達式的基礎語法
        //無參無返回
        LambdaNoneReturnNoneParm lambda1 = ()->{
            System.out.println("LambdaNoneReturnNoneParm");
        };
        lambda1.test();
        //單個參數,無返回
        LambdaNoneReturnSingleParm lambda2 = (int a)->{
            System.out.println("LambdaNoneReturnSingleParm: "+a);
        };
        lambda2.test(77);
        //多個參數,無返回
        LambdaNoneReturnMutipleParm lambda3 = (int a,int b)->{
            System.out.println("LambdaNoneReturnMutipleParm:  a:"+a+",b: "+b+",a+b: "+(a+b));
        };
        lambda3.test(10,77 );
        //無參,有返回
        LambdaSingleReturnNoneParm lambda4 = ()->{
            return 77;
        };
        int ret = lambda4.test();
        System.out.println(ret);
        //單個參數,有返回
        LambdaSingleReturnSingleParm lambda5 = (int a)->{
            return a*10;
        };
        int ret2 = lambda5.test(7);
        System.out.println(ret2);
        //多個參數,有返回
        LambdaSingleReturnMutipleParm lambda6 = (int a,int b)->{
            return a*b;
        };
        int ret3 = lambda6.test(7,11);
        System.out.println(ret3);

Lambda語法精簡

  • 參數類型,由於已經在接口的抽象方法中,已經定義了參數的數量和類型,所以在表達式中,參數的類型可以省略(參數類型要麼都省略,要麼都不省略,不能只省略其中一個)
//多個參數,無返回
 LambdaNoneReturnMutipleParm lambda = (a,b)->{
            System.out.println("LambdaNoneReturnMutipleParm:  a:"+a+",b: "+b+",a+b: "+(a+b));
        };
        lambda.test(10,77 );
  • 參數小括號,如果參數的數量只要一個,小括號可以省略
//單個參數,無返回
        LambdaNoneReturnSingleParm lambda2 = a->{
            System.out.println("LambdaNoneReturnSingleParm: "+a);
        };
        lambda2.test(77);
  • 方法大括號,如果方法體中只有一條語句,大括號可以省略
//無參無返回
       LambdaNoneReturnNoneParm lambda3 = ()-> System.out.println("LambdaNoneReturnNoneParm");
       lambda3.test();
  • 如果方法體中,唯一的一條語句是返回語句,在省略大括號的同時必須省略掉return
 LambdaSingleReturnNoneParm lambda4 = ()-> 77;
       int ret = lambda4.test();
       System.out.println(ret);

lambda語法進階

  • 方法引用:可以快速的將一個lambda表達式的實現指向一個已經實現的方法
    語法;方法的屬於者::方法名
    參數類型和數量要和接口中的方法一致,返回值也一樣

靜態方法引用:

public class syntax3 {
    public static void main(String[] args) {
        //lambda語法進階
        //方法引用:可以快速的將一個lambda表達式的實現指向一個已經實現的方法
        //語法,方法的屬於者::方法名
        //參數類型和數量要和接口中的方法一致,返回值也一樣
//        LambdaSingleReturnSingleParm lambda1 = a -> a*2;
//        LambdaSingleReturnSingleParm lambda2 = a -> a*2;
        LambdaSingleReturnSingleParm lambda1 = a -> change(a);
        int ret = lambda1.test(2);
        System.out.println("ret: "+ret);
        //方法引用
        LambdaSingleReturnSingleParm lambda2 = syntax3::change;
        int ret2 = lambda2.test(2);
        System.out.println("ret2: "+ret2);
    }
    private static int change(int a){
        return a*2;
    }
}

構造方法的引用:

先定義一個Person類

public class Person {
  private String name;
  private int age;

  @Override
  public String toString() {
      return "Person{" +
              "name='" + name + '\'' +
              ", 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;
  }

  public Person() {
      System.out.println("無參構造器");
  }

  public Person(String name, int age) {
      this.name = name;
      this.age = age;
      System.out.println("有參構造器: "+name+",age: "+age);
  }
}

        PersonCreater creater = ()->new Person();//一般的Lambda用法
         Person a = creater.getPerson();
        //無參構造方法的引用
        PersonCreater creater1 = Person::new;//構造方法引用      
        Person b =creater1.getPerson();
        //多個參數構造方法引用
        PersonCreaterWithParm creater2 = Person::new;
        Person c = creater2.getPerson("林北",21 );

-----
@FunctionalInterface
interface PersonCreater{
    Person getPerson();
}
@FunctionalInterface
interface PersonCreaterWithParm{
    Person getPerson(String name,int age);
}


Java四大核心函數式接口

在使用Lambda表達式的時候總要自己寫函數式接口嗎? 當然不是這樣了,Java8裏面提供了四大核心的函數式供我們使用

函數式接口 參數類型 返回類型 作用
Consumer T void 對類型T參數操作,無返回結果,包含方法 void accept(T t)
Supplier T 返回T類型參數,方法時 T get()
Function T R 對類型T參數操作,返回R類型參數,包含方法 R apply(T t)
Predicate T Boolean 斷言型接口,對類型T進行條件篩選操作,返回boolean,包含方法 boolean test(T t)

使用

 /**
     * Consumer<T>
     */
    @Test
    public void ConsumerTest(){
        consumer("Consumer",(m)-> System.out.println("我是ConsumerTest接口:"+m) );
    }
    public void consumer(String name, Consumer consumer){
        consumer.accept(name);
    }

    /**
     * Supplier<T>
     */
    @Test
    public void SupplierTest() {
        List<Integer> list = getNumList(7,()->(int)Math.random()*8);
        list.forEach(System.out::println);
    }
    public List<Integer> getNumList(int n, Supplier<Integer> supplier){
        List<Integer> list = new ArrayList<>();
        for(int i = 0;i<n;i++){
            Integer num = supplier.get();
            list.add(num);
        }
        return list;
    }

    /**
     * Function<T,R>
     */
    @Test
    public  void FunctionTest(){
        String str=strHandle("Hello World",(string)->string.substring(2,5 ));
        System.out.println(str);
    }

    public  String strHandle(String str, Function<String,String> fun){
        return fun.apply(str);
    }

    /**
     * Predicate<T>
     */
    @Test
    public void PredicateTest(){

        List<String> list1= Arrays.asList("Predicate","Function","Supplier","Consumer");
        List<String> list=filterList(list1,(s)->s.length()>8);
        for (String s : list) {
            System.out.println(s);
        }
    }

    public List<String>  filterList(List<String> list, Predicate<String> predicate){
        List<String> strings=new ArrayList<>();
        for (String string : list) {
            if(predicate.test(string)){
                strings.add(string);
            }
        }
        return strings;

    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章