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。