1. 程式人生 > >第三章(6)複合Lambda表示式

第三章(6)複合Lambda表示式

     你可以把多個簡單的Lambda複合成複雜的表示式。比如,你可以讓兩個謂詞之間做一個or操作,組合成一個更大的謂詞。而且,你還可以讓一個函式的結果成為另一個函式的輸入。你可能會想,函式式介面中怎麼可能有更多的方法呢?(畢竟,這違背了函式式介面的定義啊!)竅門在於,我們即將介紹的方法都是預設方法,也就是說它們不是抽象方法。我們會在第9章詳談。

1.比較器複合

我們之前說到,比較一個列表中蘋果的重量,可以像下面這樣做:

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
        Apple a1 = new Apple("國光",33);
        Apple a2 = new Apple("富士",21);
        Apple a3 = new Apple("黃元帥", 12);
        List<Apple> apples = new ArrayList<Apple>();
        apples.add(a1);
        apples.add(a2);
        apples.add(a3);
        apples.sort(Comparator.comparing(Apple::getWeight));
        for(Apple a:apples){
        	System.out.println(a.getWeight());
        }
	}

}

(1)逆序 

然而我們想要逆序,該要如何操作呢?可以像下面這樣做:

apples.sort(Comparator.comparing(Apple::getWeight).reversed());

(2)比較器璉

但如果發現有兩個蘋果一樣重怎麼辦?哪個蘋果應該排在前面呢?你可能需要再提供一個Comparator來進一步定義這個比較。比如,在按重量比較兩個蘋果之後,你可能想要按蘋果的其他屬性排序。thenComparing方法就是做這個用的。它接受一個函式作為引數(就像comparing方法一樣),如果兩個物件用第一個Comparator比較之後是一樣的,就提供第二個Comparator。你又可以優雅地解決這個問題了:

apples.sort(Comparator.comparing(Apple::getWeight).reversed().thenComparing(Apple::getName));

2.複合謂詞

謂詞介面包括三個方法:negate、and和or,讓你可以重用已有的Predicate來建立更復雜的謂詞。

(1)negate非,取反

Predicate<Apple> predicate = apple->"綠光".equals(apple.getName());
List<Apple> apps = Test.getApple(apples, predicate.negate());//取的是名字不是綠光的蘋果

 這種複合謂詞的起始呼叫位置無法直接通過lambda表示式呼叫,只能通過lambda實現的介面示例進行一次起始呼叫,隨後便可以隨意玩:

Predicate<Apple> predicate = apple->"綠光".equals(apple.getName());
List<Apple> apps = Test.getApple(apples,predicate.and(apple>20>apple.getWeight()).or(apple->apple.getName().length()>5));

3.函式複合

     最後,你還可以把Function介面所代表的Lambda表示式複合起來。Function介面為此配了andThen和compose兩個預設方法,它們都會返回Function的一個例項。andThen方法會返回一個函式,它先對輸入應用一個給定函式,再對輸出應用另一個函式。比如,假設有一個函式f給數字加1 (x -> x + 1),另一個函式g給數字乘2,你可以將它們組合成一個函式h,先給數字加1,再給結果乘2:

Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2;
Function<Integer, Integer> h = f.andThen(g);
System.out.println(h.apply(3));//打印出8

 你也可以類似地使用compose方法,先把給定的函式用作compose的引數裡面給的那個函式,然後再把函式本身用於結果。比如在上一個例子裡用compose的話,它將意味著f(g(x)),而andThen則意味著g(f(x)):

Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2;
Function<Integer, Integer> h = f.compose(g);
System.out.println(h.apply(3));//輸出7