摘要:通常我們用篩選一詞來(lái)表達(dá)這個(gè)概念。嘿,這兩個(gè)方法只有一行不同里面高亮的那行條件。詞謂詞在數(shù)學(xué)上常常用來(lái)代表一個(gè)類(lèi)似函數(shù)的東西,它接受一個(gè)參數(shù)值,并返回或。
傳遞代碼
我們首先看一個(gè)例子,假設(shè)你有一個(gè) Apple 類(lèi),它有一個(gè)getColor方法,還有一個(gè)變量inventory保存著一個(gè)Apples的列表。你可能想要選出所有的綠蘋(píng)果,并返回一個(gè)列表。通常我們用篩選(filter)一詞來(lái)表達(dá)這個(gè)概念。在Java 8之前,你可能會(huì)寫(xiě)這樣一個(gè)方法 filterGreenApples :
public static ListfilterGreenApples(List inventory){ List result = new ArrayList<>(); for (Apple apple: inventory){ if ("green".equals(apple.getColor())) { result.add(apple); } } return result; }
但是接下來(lái),有人可能想要選出重的蘋(píng)果,比如超過(guò)150克,于是你心情沉重地寫(xiě)了下面這
個(gè)方法,甚至用了復(fù)制粘貼:
public static ListfilterHeavyApples(List inventory){ List result = new ArrayList<>(); for (Apple apple: inventory){ if (apple.getWeight() > 150) { result.add(apple); } } return result; }
我們都知道軟件工程中復(fù)制粘貼的危險(xiǎn)——給一個(gè)做了更新和修正,卻忘了另一個(gè)。嘿,這
兩個(gè)方法只有一行不同: if 里面高亮的那行條件。如果這兩個(gè)高亮的方法之間的差異僅僅是接受
的重量范圍不同,那么你只要把接受的重量上下限作為參數(shù)傳遞給 filter 就行了,比如指定
(150, 1000) 來(lái)選出重的蘋(píng)果(超過(guò)150克),或者指定 (0, 80) 來(lái)選出輕的蘋(píng)果(低于80克)。
但是,我們前面提過(guò)了,Java 8會(huì)把條件代碼作為參數(shù)傳遞進(jìn)去,這樣可以避免 filter 方法
出現(xiàn)重復(fù)的代碼。現(xiàn)在你可以寫(xiě):
public static boolean isGreenApple(Apple apple) { return "green".equals(apple.getColor()); } public static boolean isHeavyApple(Apple apple) { return apple.getWeight() > 150; } static ListfilterApples(List inventory, Predicate p) { List result = new ArrayList<>(); for (Apple apple: inventory){ if (p.test(apple)) { result.add(apple); } } return result; }
要用它的話(huà),你可以寫(xiě):
filterApples(inventory, Apple::isGreenApple);
或者
filterApples(inventory, Apple::isHeavyApple);
什么是謂詞?
前面的代碼傳遞了方法 Apple::isGreenApple (它接受參數(shù) Apple 并返回一個(gè)
boolean )給 filterApples ,后者則希望接受一個(gè) Predicate參數(shù)。詞 謂詞(predicate)
在數(shù)學(xué)上常常用來(lái)代表一個(gè)類(lèi)似函數(shù)的東西,它接受一個(gè)參數(shù)值,并返回 true 或 false 。你
在后面會(huì)看到,Java 8也會(huì)允許你寫(xiě) Function——在學(xué)校學(xué)過(guò)函數(shù)卻沒(méi)學(xué)
過(guò)謂詞的讀者對(duì)此可能更熟悉,但用 Predicate是更標(biāo)準(zhǔn)的方式,效率也會(huì)更高一
點(diǎn)兒,這避免了把 boolean 封裝在 Boolean 里面。
把方法作為值來(lái)傳遞顯然很有用,但要是為類(lèi)似于 isHeavyApple 和 isGreenApple 這種可
能只用一兩次的短方法寫(xiě)一堆定義有點(diǎn)兒煩人。不過(guò)Java 8也解決了這個(gè)問(wèn)題,它引入了一套新
記法(匿名函數(shù)或Lambda),讓你可以寫(xiě)
filterApples(inventory, (Apple a) -> "green".equals(a.getColor()) );
或者
filterApples(inventory, (Apple a) -> a.getWeight() > 150 );
甚至
filterApples(inventory, (Apple a) -> a.getWeight() < 80 ||
"brown".equals(a.getColor()) );
完整的代碼為:
public class FilteringApples1 { public static void main(String[] args) { Listinventory = Arrays.asList(new FilteringApples1.Apple(80, "green"), new FilteringApples1.Apple(155, "green"), new FilteringApples1.Apple(120, "red")); List greenApples2 = filterApples(inventory, (FilteringApples1.Apple a) -> "green".equals(a.getColor())); System.out.println(greenApples2); // [Apple{color="green", weight=155}] List heavyApples2 = filterApples(inventory, (FilteringApples1.Apple a) -> a.getWeight() > 150); System.out.println(heavyApples2); // [] List weirdApples = filterApples(inventory, (FilteringApples1.Apple a) -> a.getWeight() < 80 || "brown".equals(a.getColor())); System.out.println(weirdApples); } public static List filterApples(List inventory, Predicate p) { List result = new ArrayList<>(); for (FilteringApples1.Apple apple : inventory) { if (p.test(apple)) { result.add(apple); } } return result; } public static class Apple { private int weight = 0; private String color = ""; public Apple(int weight, String color) { this.weight = weight; this.color = color; } public Integer getWeight() { return weight; } public void setWeight(Integer weight) { this.weight = weight; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String toString() { return "Apple{" + "color="" + color + """ + ", weight=" + weight + "}"; } } }
java8中內(nèi)置filter函數(shù)
staticCollection filter(Collection c, Predicate p);
這樣你甚至都不需要寫(xiě) filterApples 了,因?yàn)楸热缦惹暗恼{(diào)用
filterApples(inventory, (Apple a) -> a.getWeight() > 150 );
就可以直接調(diào)用庫(kù)方法 filter :
filter(inventory, (Apple a) -> a.getWeight() > 150 );
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/73354.html
摘要:依舊使用剛剛對(duì)蘋(píng)果排序的代碼?,F(xiàn)在,要做的是篩選出所有的綠蘋(píng)果,也許你會(huì)這一個(gè)這樣的方法在之前,基本上都是這樣寫(xiě)的,看起來(lái)也沒(méi)什么毛病。但是,現(xiàn)在又要篩選一下重量超過(guò)克的蘋(píng)果。 《Java8實(shí)戰(zhàn)》-讀書(shū)筆記第一章(01) 最近一直想寫(xiě)點(diǎn)什么東西,卻不知該怎么寫(xiě),所以就寫(xiě)寫(xiě)關(guān)于看《Java8實(shí)戰(zhàn)》的筆記吧。 第一章內(nèi)容較多,因此打算分幾篇文章來(lái)寫(xiě)。 為什么要關(guān)心Java8 自1996年J...
摘要:接口有一個(gè)方法,可以返回值。在上面的代碼中,就是獲取字符串的長(zhǎng)度,然后將每個(gè)字符串的長(zhǎng)度作為返回值返回。 今天我們還講講Consumer、Supplier、Predicate、Function這幾個(gè)接口的用法,在 Java8 的用法當(dāng)中,這幾個(gè)接口雖然沒(méi)有明目張膽的使用,但是,卻是潤(rùn)物細(xì)無(wú)聲的。為什么這么說(shuō)呢? 這幾個(gè)接口都在 java.util.function 包下的,分別是Con...
摘要:但是到了第二天,他突然告訴你其實(shí)我還想找出所有重量超過(guò)克的蘋(píng)果?,F(xiàn)在,農(nóng)民要求需要篩選紅蘋(píng)果。那么,我們就可以根據(jù)條件創(chuàng)建一個(gè)類(lèi)并且實(shí)現(xiàn)通過(guò)謂詞篩選紅蘋(píng)果并且是重蘋(píng)果酷,現(xiàn)在方法的行為已經(jīng)取決于通過(guò)對(duì)象來(lái)實(shí)現(xiàn)了。 通過(guò)行為參數(shù)化傳遞代碼 行為參數(shù)化 在《Java8實(shí)戰(zhàn)》第二章主要介紹的是通過(guò)行為參數(shù)化傳遞代碼,那么就來(lái)了解一下什么是行為參數(shù)化吧。 在軟件工程中,一個(gè)從所周知的問(wèn)題就是,...
摘要:示例字符串?dāng)?shù)值算術(shù)和文件原文譯者飛龍協(xié)議大量的教程和文章都涉及到中最重要的改變,例如表達(dá)式和函數(shù)式數(shù)據(jù)流。不僅僅是字符串,正則表達(dá)式模式串也能受益于數(shù)據(jù)流。 Java 8 API 示例:字符串、數(shù)值、算術(shù)和文件 原文:Java 8 API by Example: Strings, Numbers, Math and Files 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 ...
大概一年多之前,我對(duì)java8的理解還僅限一些只言片語(yǔ)的文章之上,后來(lái)出于對(duì)函數(shù)式編程的興趣,買(mǎi)了本參考書(shū)看了一遍,然后放在了書(shū)架上,后來(lái),當(dāng)我接手大客戶(hù)應(yīng)用的開(kāi)發(fā)工作之后,java8的一些工具,對(duì)我的效率有了不小的提升,因此想記錄一下java8的一些常用場(chǎng)景,我希望這會(huì)成為一個(gè)小字典,能讓我免于頻繁翻書(shū),但是總能找到自己想找的知識(shí)。 用于舉例的model: @Data public class ...
閱讀 1850·2023-04-26 00:59
閱讀 3142·2021-11-15 18:10
閱讀 3088·2021-09-22 16:02
閱讀 772·2021-09-02 15:15
閱讀 3726·2019-08-30 15:56
閱讀 1925·2019-08-30 15:54
閱讀 2869·2019-08-29 16:31
閱讀 2044·2019-08-29 16:10