函數語言程式設計初探(與泛型方法的結合)
阿新 • • 發佈:2022-03-09
平時在操作集合時,常常有這麼一種需求,就是查詢符合某一種條件的元素在不在集合中,比如現在有個List<User>,我們想知道這個集合裡有沒有名字叫張三的人,有的話會做123,沒有的話會做456之類的。
一般我們會寫以下程式碼
List<User> collect = list.stream().filter(p -> "張三".equals(p.getName())).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(collect)){ //do something}else { //do something }
如果在一個方法裡,需要頻繁這麼操作,那未免顯得有些繁瑣,所以可以把這個判斷操作抽出來作為一個函式呼叫,既然是集合,那就需要支援泛型,所以有了以下方法
private <T> boolean findInList(Collection<? extends T> collection, Predicate<? super T> test){ for (T t : collection) { if (test.test(t)){return true; } } return false; }
針對一個集合,給定一個Predicate,遍歷這個集合,如果有一個元素滿足Predicate的要求,那就返回true,否則返回false,所以上面的判斷方法可以簡化成
if (findInList(list,b -> "張三".equals(b.getName()))){ //do something }else { //do something }
更進一步,我們可以把註釋的do something也抽象成一個函式式方法,如果我們需要在找到特定元素之後對這個元素做什麼,那可以在後面加一個Consumer
private <T> void ifInListDo(Collection<? extends T> collection,Predicate<? super T> test, Consumer<? super T> action){ for (T t : collection) { if (test.test(t)){ action.accept(t); } } }
比如我們想在找到名字叫張三的人之後輸出他的分數,那麼就可以有以下程式碼
ifInListDo(list,a -> "張三".equals(a.getName()),(a)->{System.out.println("張三的分數 : " + a.getScore());});
或者我們需要找到這個元素之後返回另一個元素,那可以把Consumer換成Supplier,如下
private <T> T ifInListGet(Collection<? extends T> collection,Predicate<? super T> test, Supplier<? extends T> action){ for (T t : collection) { if (test.test(t)){ return action.get(); } } return null; }
就可以像這樣呼叫
User b = ifInListGet(list,a -> "張三".equals(a.getName()),()-> User.builder().Name("李四").build());
這個意思是如果list裡有張三,那就得到了一個叫李四的User物件
最後,如果我們找到張三後,想根據張三的某些屬性返回一個新物件,那可以將Supplier換成原始的Function
private <T> T ifInListGet(Collection<? extends T> collection,Predicate<? super T> test, Function<? super T, ? extends T> action){ for (T t : collection) { if (test.test(t)){ return action.apply(t); } } return null; }
呼叫如下
User b = ifInListGet(list,a -> "張三".equals(a.getName()),(b)-> User.builder().Name("李四").Score(b.getScore()).build());
就是講張三的分數賦值給新返回的李四了
函式式風格的程式碼比較簡潔流暢,但是可維護性就見仁見智了,以上