1. 程式人生 > >java函數語言程式設計入門教程

java函數語言程式設計入門教程

什麼是函數語言程式設計

在介紹函數語言程式設計前,先了解一下平時我們所使用指令式程式設計,指令式程式設計是告訴計算機如何一步一步執行程式設計風格。
比如我們要在一個蘋果的物件集合中篩選出顏色為紅色的蘋果集合。我們需要寫以下程式碼:

  1. 建立儲存蘋果的集合list
  2. 遍歷這個集合
  3. 判斷蘋果顏色是不是為紅色,如果滿足條件,加入結果集合
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進行分析,其中涉及的大量的函數語言程式設計的使用。