Java函數式編程:二、高階函數,閉包,函數組合以及柯里化

承接上文:Java函數式編程:一、函數式接口 , lambda表達式和方法引用這次來聊聊函數式編程中其他的幾個比較重要的概念和技術,從而使得我們能更深刻的掌握Java中的函數式編程 。本篇博客主要聊聊以下幾個問題

  • 高階函數
  • 閉包概念
  • 函數組合處理函數的使用
  • 柯里化以及部分求值下面開始:
1、高階函數高階函數這里指的可不是數學里的那個,這里主要要從維度這個概念理解,什么叫高維?如果a是一維 , 那么生成a的存在就是高維 。在這里 , 函數就是這個a , 高階函數指的就是能生成函數或是以函數為參數的函數
定義:高階函數是一個能接受函數作為參數或能夠把函數作為返回值的函數 。
public interface Function{String str(String s);}public class Procudure{// 下面就是一個標準的高階函數public Function(String s){return s -> s.upperCase();}}這里有兩點:
  • 我們可以通過繼承java.util.function中的接口,或是自定義一個函數式接口來為專門的接口創建別名
  • 有了lambda表達式,很明顯,我們很輕松就能創建并返回一個函數
但是這只是基本的,還記得函數式編程的意義嗎?這里的關鍵在于,有時候,我們可以根據接受的函數,讓高階函數生成一個新的函數 。
public class test {public static Function<String, String> transform(Function<String, String> f){return f.andThen(String::toUpperCase);}public static void main(String[] args) {Function<String, String> transform = test2.transform(str -> {return str.substring(0, 2);});String s = transform.apply("abcdefg");System.out.println(s);}}可以看到,這里我們通過andThen()這個Function接口的通用方法,連接了前后兩個方法 , 并且使得無論我們輸入了什么,都會將該字符串轉化為全大寫,后面我們輸入了一個截取前兩個字符作為返回值的方法,但很明顯,這里可以有更多的選擇,并且我們實際上也可以通過方法引用來引用某些定義好的函數,非常靈活 。
2、閉包什么是閉包?
考慮一個lambda表達式 , 它使用了其函數作用域之外的變量 。當返回該函數時會發生什么呢?也即,當我們通過調用lambda表達式產生的匿名方法引用這些外部變量會發生什么呢?
如果一門語言能夠解決這個問題,我們就認為該語言是支持閉包的,或者也可以說它支持詞法作用域 。
這里還涉及到一個術語:變量捕獲
【Java函數式編程:二、高階函數,閉包,函數組合以及柯里化】上面聽起來是不是不明白,沒關系,給個例子:
public class Example{IntSupplier plus(int x){int y = 1;return () -> x + y;}}考慮這個類和其中的方法plus(int x),你會不會發現有一些問題 。
因為我們的plus(int x)方法返回的是一個函數 , 這里假設返回的函數是f(int x),也就是說,f(int x)返回時,plus(int x)已經執行結束,所以其中的變量int y = 1;已經脫離了作用域,那么等到我們獲取了f(int x)的對象再調用到f(int x)方法時,這個y要怎么辦呢?
你會發現 , 上面的這個方法是可以被編譯執行成功的,但是下面的這個就不行:
public class Example{IntSupplier plus(int x){int y = 1;return () -> x + (++y);}}為什么呢?編譯器提示:

    推薦閱讀