1. 程式人生 > >Java8之寫一個裝逼的函式式程式碼

Java8之寫一個裝逼的函式式程式碼

Java8之將普通方法寫一個裝逼的函式式程式碼

首先看程式碼

下面的方法很簡單就是從資料中找一個值,找到返回。

    @Test
    public void test2() {
        Integer [] c = new Integer[20];
        for(int i = 0;i< c.length; i++) {
            c[i]=i;
        }
        //從上面這個陣列中找一個值
        int findValue = find(c, 2);
        System.err.println(findValue);
    }
    private
Integer find(Integer[] x, int y) { for (int i = 0; i < x.length; i++) { if (x[i].intValue() == y) return x[i]; } return null; }

Java8修改成函式式,變成以一下這個樣子

    @Test
    public void test1() {
    int size = 20;
    Integer [] c =  Stream.iterate(size - 1
, x -> x-1).limit(size).toArray(Integer[]::new); Integer result =find1(c, 2, (x,y)->{ return Arrays.stream(x).filter(n->n.intValue()==y).findFirst().orElse(null); }); System.err.println(result); } public static Integer find1(Integer[] x,Integer y,BiFunction<Integer[], Integer, Integer> t) { return
t.apply(x, y); }

或者變成這個樣子

    @Test
    public void test1() {
        int size = 20;
    Integer [] c =  Stream.iterate(size - 1, x -> x-1).limit(size).toArray(Integer[]::new);
        Integer result = find13(c, 2);      
        System.err.println(result);
    }
    public Integer find13(Integer[] x, Integer y) {
        BiFunction<Integer[], Integer, Integer> f = (m, n) -> {
            return Arrays.stream(m).filter(i -> i.intValue() == n).findFirst().orElse(null);
        };
        return f.apply(x, y);
    }

這裡BiFunction是Java8已定義的一個函式介面
Interface BiFunction<T,U,R> 其中 引數型別如下
T - 函式的第一個引數的型別
U - 函式的第二個引數的型別
R - 函式結果的型別
如果覺得看不明白,也可以自定義一個自己的函式介面
這時上面的方法就變成下面這樣:

    @Test
    public void test1() {
        int size = 20;
    Integer [] c =  Stream.iterate(size - 1, x -> x-1).limit(size).toArray(Integer[]::new);
        Integer result = find13(c, 2);
        System.err.println(result);
    }

    public Integer find13(Integer[] x, Integer y) {
        F1 f1 = (m, n) -> {
            return Arrays.stream(m).filter(i -> i.intValue() == n).findFirst().orElse(null);
        };
        return f1.find(x, y);
    }

    @FunctionalInterface
    interface F1{
     Integer find(Integer [] r,Integer u);
    }

其中F1為自定義的函式介面,只包含一個抽象方法。可以看java8 總結 之lambda表示式來了解什麼時函式介面。

如果你有一定的函數語言程式設計經驗,是不是感覺怪怪的。這是因為在Java中lambda表示式,其實還是一個介面。要想寫一個靈活的函式表示式,首先要定義一個只包含一個抽象方法的介面,還好,Java8已經自定義好了絕大部分你能用到的介面:

常用函式式介面

函式式介面 引數型別 返回型別 抽象方法名 描述 其它方法
Runnable void run 執行一個沒有引數和返回值的操作
Supplier T get 提供一個T返回值
Consumer T void accept 處理一個T型別的值 chain
BiConsumer T,U void accept 處理T型別和U型別的值 chain
Function T R apply 表示接受一個引數T處理併產生結果R compose,andThen,compose,identity
BiFunction T,U R apply 表示接受兩個引數(T,U)併產生結果R andThen
UnaryOperator T T apply 對型別T進行的一元操作,並返回T型別 andThen, apply, compose
BinaryOperator T T apply 對型別T進行的二元操作 andThen
Predicate T boolean test 一個計算Boolean值的函式 And,or,negate,isEqual
BiPredicate T,U boolean test 一個含有兩個引數,計算Boolean的函式 And,or,negate

以上是比較常用的幾個,上面的例子中用至的就是BiFunction函式介面。
如果要了解更多可以檢視JDK1.8下java.util.function或者檢視線上API

寫裝X函式式程式碼的方式

寫出箭頭函式

如上,定義或者使用已有的函式式介面,如上面的F1介面或者 BiFunction介面都是這類的介面,定義好後,在呼叫至該介面的抽象方法時,就要知道,這些介面可以將函式做為引數來傳遞。要有這個思想轉變。

消除for/while迴圈

原則上,函數語言程式設計不應該有迴圈的,對於迴圈Java8對集合類的幾乎都可以轉為Stream,Stream豐富操作完全可以滿足日常常用操作。
只要記住函數語言程式設計的“函式式”特性:不可變資料,第一類物件以及尾呼叫優化。
要想了解的話可以至左耳朵耗子的部落格看一下價紹。

結束 end.
下一篇我們來說說Java8系列最後一篇對併發的增強以及新日期的API。