函數式編程優點
1.大數據下處理集合效率高(並行流,不用自己寫多線程處理)
2.代碼簡潔,可讀性好(後面章節實戰會體現)
3.不學看不懂公司的代碼
https://www.bilibili.com/video/BV1Gh41187uR?p=39&vd_source=b2e596b686781ec41de76995b33cfe21
Lambda表達式
Lambda是函數式編程的基石,可以對某些匿名內部類的寫法進行簡化。
不關注是什麼對象,只關注對什麼數據操作。
基本格式:
(參數列表)——>{代碼}
舉例:
創建線程並啓動使用匿名內部類和Lambda方式如下:
new Thread(new Runnable() { @Override public void run() { System.out.println("hello"); } }); new Thread(()->{ System.out.println("hello"); });
由此可見:匿名內部類 需要關注接口名和方法名
lambda表達式只關注方法參數和方法體(具體操作)。
練習:
定義一個方法,接收一個接口
public static void printNum(IntPredicate intPredicate){
int[] arr={1,2,3,4,5,6,7};
for (int i : arr) {
if (intPredicate.test(i)){
System.out.println(i);
}
}
}
使用匿名內部類和Lambda分別調用此方法。
printNum(new IntPredicate() { @Override public boolean test(int value) { return value%2==0; } }); printNum((int value)->{ return value%2==0; });
Lambda表達式省略規則:
1.參數類型可以省略。
2.方法體只有一句話時大括號return和唯一一句代碼的分號可以省略。
3.方法只有一個參數時,小括號可以省略。
上面的例子可以寫成如下:
printNum(value-> value%2==0);
Stream流
有了Lambda表達式的基礎,可以接下來了解Stream流了(函數式編程最重要的一部分)
Stream流可以更方便的對集合 數組進行操作
1.如下是最簡單的一個Stream操作集合:有常用的三個操作 分別是創建流 中間操作 終結操作
list.stream()//創建流 .distinct()// 中間操作 .filter(emp -> emp.getAge()>=18)// 中間操作 .forEach(emp -> System.out.println(emp.getAge()));//終結操作
如果不寫終結操作,前面的中間操作是不會被調用的
有很多個終結操作和中間操作,大家慢慢查去吧 這裏只簡單介紹一下。
2.在介紹一個終結操作collect:把當前流轉換成一個集合。
如下:轉成Map
list.stream() .distinct() .filter(emp -> emp.getAge()>=18) .collect(Collectors.toMap(emp -> emp.getAge(),emp -> emp));
常見的函數式接口
介紹一下JDK給我們提供的常用函數式接口。
1.Function計算轉換接口
根據抽象方法的參數列表和返回值類型我們知道,我們可以在方法中對傳入的參數計算或轉換,把結果返回。
@FunctionalInterface public interface Function<T, R> { /** * Applies this function to the given argument. * * @param t the function argument * @return the function result */ R apply(T t);
定義一個接口 接收Function函數
static Double change(int base, Function<Integer,Double> function){ Double res = function.apply(base); return res; }
調用帶有Function參數的函數
Double res = change(1000, (Integer integer) -> {
// 這裏是業務邏輯 return integer * 1.2; });
現在也可以看到在調用change函數的時候,我們只關心參數和方法實現.
2.Supplier生產型接口
根據抽象方法的參數列表和返回值類型我們知道,我們可以在方法中創建對象,把創建好的對象返回。
@FunctionalInterface public interface Supplier<T> { /** * Gets a result. * * @return a result */ T get(); }
定義一個接口 接收supplier參數:如果emp的年齡大於傳入的age就設置爲成年。
static void testSupplier(int age, Supplier<Emp> supplier){ Emp emp =supplier.get(); if (supplier.get().getAge()>age){ emp.setAdultFlag(true); } emp.setAdultFlag(false); }
調用該接口
testSupplier(18,()->{
//do some thing return new Emp(19); });