java函數語言程式設計入門教程
什麼是函數語言程式設計
在介紹函數語言程式設計前,先了解一下平時我們所使用指令式程式設計,指令式程式設計是告訴計算機如何一步一步執行程式設計風格。
比如我們要在一個蘋果的物件集合中篩選出顏色為紅色的蘋果集合。我們需要寫以下程式碼:
- 建立儲存蘋果的集合list
- 遍歷這個集合
- 判斷蘋果顏色是不是為紅色,如果滿足條件,加入結果集合
public static List<Apple> getRedAppleDeclarative(List<Apple> apples) { List<Apple> results = new ArrayList<> (); for (Apple apple : apples) { if("red".equals (apple.getColor ())){ results.add (apple); } } return results; }
那麼函數語言程式設計是怎樣進行操作的呢?函數語言程式設計類似於我們的sql語句
select * from table where 條件語句
只宣告我想要什麼,以及條件即可
public static List<Apple> getRedAppleFunctional(List<Apple> apples) {
return apples.stream ().filter (apple -> "red".equals (apple.getColor ())).collect (Collectors.toList ());
}
可以看到通過函數語言程式設計大大簡化了程式碼語句,同時如果對函式式結構熟悉的話,很快便可知道這段程式碼的含義:stream獲取apples集合流-filter過濾滿足的條件-collect轉化為list輸出
相比於繁瑣的命令式程式碼,我們函數語言程式設計可以令程式碼瞬間充滿小清新學院風,話不多說,趕緊學習起來以備下次裝B之需吧。
通過與數學函式的對比加深理解函數語言程式設計
我們都知道數學的中函式思想,比如根據輸入x求的y的值,我們用數學函式表示 y=f(x) = x+10, x為輸入,以x+10為結果做為條件
那麼用java函數語言程式設計風格可以表示為
Function<Integer,Integer> function = (x)->{return x+10;};
具體呼叫:
public static Integer calculate(Function<Integer,Integer> function){ return function.apply (10); } public static void main(String[] args) { Function<Integer,Integer> function = (x)->{return x+10;}; Integer result = calculate (function); }
在上面的程式碼中我們看到,main函式中我們定義的function 就是數學中的函式f(x) ,我們把定義好的函式傳給方法caculate, caculate中function.apply(10)就相當於我們呼叫了數學函式f(10).
lambda表示式
我們上面Function介面來表達資料函式f(x) = x+10,這個function就是一個lambda表示式,lamdba表示式由引數箭頭和主體構成,基本語法為: (引數)->表達語句
使用lamdba的好處是非常直觀,程式設計者的意圖十分明顯的表現在lambda表示式裡。
java8為lambda是使用提供了一個function包,提供lambda介面,比如上面我們使用過的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);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
...
}
可以看到在Function介面中,除了default修飾的方法外,介面中只能有一個方法apply,這也是使用lambda介面的必要條件。他表示給定一個輸入T,返回一個輸出R,使用lamdba介面時,我們使用表示式來表示實現介面的唯一方法apply()
Function<Integer,Integer> function = (x)->{
System.out.println("x : "+ String.valueof(x));
return x+10;
};
lambda表示式的另一種表現形式為 lambda方法引用:
lambda方法引用 通過描述符號 :: 來區分類和方法 ::前面是類名;後面是方法,但是不加括號
//lamdba
Predicate<String> q = (String a) -> {
return a.isEmpty ();
};
使用方法引用來表示的話:
Predicate<String> p = String::isEmpty;
具體呼叫:
public class LambdaTest {
public static void lambdaFunc(Consumer<String> consumer, Predicate<String> predicate,String test) {
boolean condition = predicate.test ("");
if(condition){
consumer.accept (test);
}
}
public static void main(String[] args) {
Predicate<String> p = String::isEmpty;
Consumer<String> c = System.out::println;
lambdaFunc (c,p,"test");
}
}
上面程式碼表示如果方法引數test不為空,則進行列印
lambda引用還包括 代替函式式介面和建構函式引用
代替函式式介面:
例1:
List<String> testList = Arrays.asList ("a", "b", "A", "B");
// testList.sort ((s1, s2) -> s1.compareToIgnoreCase (s2));
testList.sort (String::compareToIgnoreCase);
System.out.println (testList);
例2:
public static void main(String[] args) {
// Function<String, Integer> f1 = (String a) -> {return Integer.valueOf (a);};
Function<String, Integer> f2 = Integer::valueOf;
Integer result = f2.apply ("2");
System.out.println (result);
}
Function中的泛型 String代表返回型別,Integer代表輸入型別,在lambda引用中會根據泛型來進行型別推斷。
建構函式引用:
//方法引用之建構函式引用
public void constructQuote(){
// Supplier<QuoteClass> s1 = () -> new QuoteClass ();
Supplier<QuoteClass> s2 = QuoteClass::new;
}
例子中Supplier 返回一個泛型中類的例項。
以上是函數語言程式設計和lambda的介紹,接下來我們會對java中的stream進行分析,其中涉及的大量的函數語言程式設計的使用。