在這篇文章中,我将讨論利用 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