天天看點

Java 8:使用compose和andThen組合函數

在這篇文章中,我将讨論利用 function 接口提供的兩個組合函數—— compose 和 andthen 來實作函數的組合。

什麼是函數組合?

首先需要建立一些小的可重用函數,然後将這些小函數組合為新函數。

現在,我們怎麼利用 compose 和 andthen 方法來完成函數的組合?

首先,定義兩個簡單的函數—— times2 和 squared。

function<integer, integer> times2 = e -> e * 2; 

function<integer, integer> squared = e -> e * e; 

接下來,使用 compose 和 andthen 将它們連起來。

times2.compose(squared).apply(4);  

// returns 32 

times2.andthen(squared).apply(4);  

// returns 64 

如你所見,compose 和 andthen 的不同之處是函數執行的順序不同。compose 函數先執行參數,然後執行調用者,而 andthen 先執行調用者,然後再執行參數。

我們開始組合函數

我們先建立一個示例,示範如何利用這種方式建立可重用的小代碼片段——然後我們以不同的方式組合這些代碼片段。

考慮下面的問題。

有一個文章清單,現在需要根據不同的需求來過濾這些文章。

首先,我們介紹兩個基本功能—— byauthor 和 bytag——基于作者和标簽來過濾文章。

bifunction<string, list<article>, list<article>> byauthor = 

    (name, articles) -> articles.stream() 

        .filter(a -> a.getauthor().equals(name)) 

        .collect(collectors.tolist()); 

bifunction<string, list<article>, list<article>> bytag =  

    (tag, articles) -> articles.stream() 

        .filter(a -> a.gettags().contains(tag)) 

兩個函數都是 bifunction——意味着需要兩個參數。

byauthor 接收作者名稱和文章清單兩個參數,傳回根據作者過濾後的文章清單。

bytag 與此相同,接收标簽和文章清單兩個參數,傳回根據标簽過濾後的文章清單。

由于 bifunction 接收兩個參數,它隻提供 andthen 函數。你不能将一個函數的結果放在一個接收兩個參數的函數中,是以沒有 compose 函數。

繼續,我們還有一個基本功能,需對文章清單從新到舊進行排序,并傳回排序後的文章清單。

function<list<article>, list<article>> sortbydate =  

    articles -> articles.stream() 

        .sorted((x, y) -> y.published().compareto(x.published())) 

function<list<article>, optional<article>> first =  

    a -> a.stream().findfirst(); 

現在,我們已經有了基本的函數,現在看我們怎麼利用這些函數來組合成新的函數。

首先,我們組合一個傳回最近發表的文章清單函數。

function<list<article>, optional<article>> newest =  

    first.compose(sortbydate); 

使用 first 這個函數以及我們之前建立的 sortbydate,我們能建立一個新的函數,該函數傳回給定文章清單的最新文章。

我們可以繼續通過不同的方式混合這些函數,進而可以組合出不同意義的函數,而不需要重複寫代碼。

找出作者的最新文章:

bifunction<string, list<article>, optional<article>> newestbyauthor =  

    byauthor.andthen(newest); 

或者對某一作者的文章進行排序

bifunction<string, list<article>, list<article>> byauthorsorted =  

    byauthor.andthen(sortbydate); 

或者你可能不關心作者,隻想根據你喜歡标簽擷取最新的文章:

bifunction<string, list<article>, optional<article>> newestbytag =  

    bytag.andthen(newest); 

我想要表達的觀點是:通過 function 接口及其組合功能,可以建立小的代碼塊,再将其組合來滿足你的需求,這樣可以可以更簡單、更有意思地實作 dry 原則。

就這樣了——利用 compose 和 andthen 來使用簡單的方式組合功能。你也試試吧!

來源:51cto