深刻理解lambda表達式與@FunctionalInterface函數式接口(一)

1、集合遍歷與Lambda表達式 引入

package com.java.design.java8;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.*;
import java.util.function.Consumer;

/**
 * @author 陳楊
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class ErgodicList {


    @Test
    public void testErgodicList() {

        //  直接構造集合對象 保證了集合size>0
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);


        System.out.println("---------------------------傳統for循環--------------------\n");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

        System.out.println("---------------------------加強for循環--------------------\n");
        for (Integer i : list) {
            System.out.println(i);
        }

        System.out.println("---------------------------迭代器-------------------------\n");

        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()) {
            Integer integer = iterator.next();
            System.out.println(integer);
        }


        System.out.println("---------------------------forEach------------------------\n");
        list.forEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                System.out.println(integer);
            }
        });

2、 @FunctionalInterface函數式接口與Lambda表達式

一、概念java

//  Consumer  @FunctionalInterface函數式接口

//  Conceptually, a functional interface has exactly one abstract method.
//  從概念上看,一個函數式接口有且只有一個精確的抽象方法
//  從java8開始 接口中不單單存在抽象方法 還能存在有具體實現的方法(默認方法)

二、 函數式接口的區分spring

//  Since {@linkplain java.lang.reflect.Method#isDefault()
//  default methods} have an implementation, they are not abstract.  If
//  an interface declares an abstract method overriding one of the
//  public methods of {@code java.lang.Object}, that also does
//  <em>not</em> count toward the interface's abstract method count
//  since any implementation of the interface will have an
//  implementation from {@code java.lang.Object} or elsewhere.
//  由於java.lang.reflect.Method#isDefault() default methods  有一個實現  因此不是抽象的
//  若是一個接口聲明一個抽象方法,其實現了java.lang.Object類中public方法:不計入抽象方法的個數

三、函數式接口的實例化方式express

//  Note that instances of functional interfaces can be created with
//  lambda expressions, method references, or constructor references.
//  函數式接口的實例化: lambda表達式 方法引用 構造方法引用

四、函數式接口中的默認方法編程

//   default void forEach(Consumer<? super T> action) {
//       Objects.requireNonNull(action);
//       for (T t : this) {
//           action.accept(t);
//       }
//   }

//   action  針對每一個元素  執行的動做行爲
//   default 修飾接口      已實現的默認方法

五、總結與思考app

//  一、若是一個接口中有且只有一個抽象方法 則其爲一個函數式接口
//  二、若是一個接口上聲明瞭@FunctionalInterface註解 則編譯器會按照函數式接口的定義來要求該接口

//  If a type is annotated with this annotation type, compilers are
//  required to generate an error message unless:
//  (1)The type is an interface type and not an annotation type, enum, or class.
//  (2)The annotated type satisfies the requirements of a functional interface.
//  However, the compiler will treat any interface meeting the
//  definition of a functional interface as a functional interface
//  regardless of whether or not a {@code FunctionalInterface}
//  annotation is present on the interface declaration.

//  三、若是接口上只有一個抽象方法,但咱們沒有對其加上@FunctionalInterface 編譯器仍然將其看做函數式接口
//     加上註解後 一目瞭然  若是沒有知足強制性要求 則會拋出錯誤信息

//  四、只有一個抽象方法的接口 有必要加上 @FunctionalInterface 如 Runnable接口
//  五、全部的函數式接口 均可以使用lambda表達式 實現(表達易懂 簡單)

3、函數式接口實例化 之 Lambda表達式

System.out.println("--------------------lambda建立函數式接口實例---------------\n");
list.forEach(i -> {
    //  若能推斷出i的類型 不須要聲明
    //  如不能推斷出(Integer i)->{}
    System.out.println(i);
});

4、在排序過程當中 Lambda表達式的 演變

System.out.println("--------------------------lambda排序-----------------------\n");

//  Collections.sort(list, new Comparator<Integer>() {
//      @Override
//      public int compare(Integer o1, Integer o2) {
//         return o2.compareTo(o1);
//     }
//  });

//  Collections.sort(list,(String o1, String o2)->{return  o2.compareTo(o1);});
//  Collections.sort(list, (o1, o2) -> { return o2.compareTo(o1); });
//  statement { return o2.compareTo(o1); }
//  expression  o2.compareTo(o1)
//  Collections.sort(list,(String::compareTo));
//  Collections.sort(list,Collections.reverseOrder());

Collections.sort(list, (o1, o2) -> o2.compareTo(o1));
System.out.println(list);

5、函數式接口實例化 之 方法引用

System.out.println("--------------------方法引用建立函數式接口實例--------------\n");
list.forEach(System.out::println);
   }
}

6、深刻理解Lambda表達式

//  lambda表達式:

//  一、從函數式編程角度來看:
//  lambda表達式爲Java添加了函數式編程的新特性 函數升格成爲一等公民
//  在函數做爲一等公民的語言 如Python中 lambda表達式爲函數類型
//  但在java中 lambda表達式是對象類型 依賴於函數式接口Functional Interface

//   二、lambda表達式書寫
//   lambda表達式形式 () -> {} 必需根據上下文肯定其匿名函數類型  函數方法 -> 函數實現
//   () 省略  參數只有一個且類型可根據上下文推導
//   {} 省略  方法體主體只有一條語句,返回值類型與主體表達式(匿名函數)一致


//  三、進一步理解lambda表達式
//  lambda表達式傳遞行爲action 不單單是值的傳遞 (類比Node.js的事件驅動 與 回調函數callback)
//  lambda表達式替換前: 事先定義對象及所持有的方法 根據 「對象.方法」 進行方法的調用 預先定義好的action
//  lambda表達式替換後: {} 方法調用 R apply(T t); 事先不知道action  僅在調用時才知道 action
//  提高抽象層次 API重用性 使用靈活
相關文章
相關標籤/搜索