轉自 http://www.wxueyuan.com/blog/articles/2017/10/20/1508487961684.html
在上一篇博客中我們一起學習了使用方法引用的方式來重複使用現有的方法並直接傳遞它們,方法引用能夠進一步地簡化我們的Lambda表達式。在實際問題的處理中,有時候我們需要多個Lambda表達式同時進行工作,Java 同樣允許我們將多個簡單的Lambda表達式複合成一個更復雜,完成功能更多的複雜表達式。比如,我們可以將兩個謂詞做一個or的操作,從而組成一個更強大的謂詞;或者我們可以讓一個函數的結果變成另一個函數的輸入(類似於鏈式處理)。
- 比較器複合(Comparator的複合)
1.逆序比較器
- Comparator reversed() 返回一個逆序後的Comparator
students.sort(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// TODO Auto-generated method stub
return o1.getAvgScore().compareTo(o2.getAvgScore());
}
}.reversed());
2.比較器鏈
如果使用了上面的比較器後,發現兩個學生的平均成績相同,你可能希望此時按照它們的身高進行排列。此時我們就需要
Comparator<T> thenComparing(Comparator<? super T> other)這個方法來設定當第一個比較器中比較的兩個元素相同時該如何進行排序。
students.sort(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// TODO Auto-generated method stub
return o1.getAvgScore().compareTo(o2.getAvgScore());
}
}.reversed().thenComparing(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// TODO Auto-generated method stub
return o1.getHeight().compareTo(o2.getHeight());
}
}));
謂詞複合(Predicate複合)
謂詞的接口中提供了:negate,and和or三個方法,有點類似於我們邏輯運算符中的非,與還有或。比如:
Predicate<Student> highStudents = s -> s.getHeight()>=180;
比如我們想要獲得身高小於180cm的學生:
Predicate<Student> notHighStudents = highStudents.negate();
我們還可以將兩個謂詞條件結合起來,比如獲得身高大於180cm,且平均分大於90的學生
Predicate<Student> highAndHighScoreStudents = highStudents.and(s -> s.getAvgScore()>90);
我們還可以進一步組合謂詞,比如要不然是身高大於180且平均分大於90分,要不然是平均分小於60的學生
Predicate<Student> complicatedPredicate = highStudents.and(s -> s.getAvgScore()>90).or(s -> s.getAvgScore()<60);
這種複合的表達式滿足了我們更多的需求,但是讀起來確仍然和問題的陳述差不多。需要注意的是,and和or方法是按照在表達式鏈中的位置,從左向右確定優先級的。因此a.or(b).and(c)也可以看作是 (a||b) && c
- 函數複合
我們同樣可以把Function接口所代表的Lambda表達式複合起來。Function接口提供了兩個andThen和compose兩個默認方法,它們都會返回Function的一個實例。
andThen方法會返回一個函數,它會將輸入應用給調用這個方法的函數,再將結果應用給這個方法的參數函數。聽起來有一些抽象,我們一起來看一個例子:
Function<Integer,Integer> f = x ->x + 1; Function<Integer,Integer> g = x ->x * 2; //先將參數x傳入給調用andThen方法的f函數,再將f函數的結果傳給andThen方法的參數g函數,得到返回值 Function<Integer,Integer> h = f.andThen(g); //結果返回是4 System.out.println(h.apply(1));
相似的compose方法,執行順序與andThen相反,它會先將輸入應用給方法參數的函數,再將結果應用給調用這個方法的函數,還是上面的那個例子:
Function<Integer,Integer> f = x ->x + 1; Function<Integer,Integer> g = x ->x * 2; //先將參數x傳入給compose方法的參數g函數,再將g函數的結果傳給調用compose方法的f函數,得到返回值 Function<Integer,Integer> h = f.compose(g); //結果返回是3 System.out.println(h.apply(1));
下圖說明了這兩個方法的區別