聚合操作
你使用集合做什么?你不可能簡單地將對象存儲在集合中并將它們留在那里,在大多數情況下,使用集合檢索存儲在其中的項。
再次考慮Lambda表達式小節中描述的場景,假設你正在創建一個社交網絡應用程序,你希望創建一個功能,使管理員能夠對滿足某些條件的社交網絡應用程序的成員執行任何類型的操作,例如發送消息。
如前所述,假設這個社交網絡應用程序的成員由以下Person類表示:
public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; // ... public int getAge() { // ... } public String getName() { // ... } }
下面的示例使用for-each循環打印集合roster中包含的所有成員的名稱:
for (Person p : roster) { System.out.println(p.getName()); }
下面的示例打印集合roster中包含的所有成員,但使用集合操作forEach:
roster .stream() .forEach(e -> System.out.println(e.getName());
盡管在本例中,使用聚合操作的版本比使用for-each循環的版本要長,但是你將看到,對于更復雜的任務,使用批量數據操作的版本將更加簡潔。
在示例BulkDataOperationsExamples中找到本節中描述的代碼摘錄。
管道和流管道是聚合操作的序列,下面的示例打印集合roster中包含的男性成員,其中包含由聚合操作filter和forEach組成的管道:
roster .stream() .filter(e -> e.getGender() == Person.Sex.MALE) .forEach(e -> System.out.println(e.getName()));
將此示例與下面的示例進行比較,下面的示例打印集合roster中包含的男性成員,并使用for-each循環:
for (Person p : roster) { if (p.getGender() == Person.Sex.MALE) { System.out.println(p.getName()); } }
管道包含以下組件:
源:可以是集合、數組、生成器函數或I/O通道,在本例中,源是集合roster。
零或多個中間操作,中間操作(如filter)生成一個新的流。
流是元素的序列,與集合不同,它不是存儲元素的數據結構,相反,流通過管道攜帶來自源的值,這個示例通過調用方法stream從集合roster創建一個流。
filter操作返回一個新的流,其中包含與其predicate匹配的元素(此操作的參數),在本例中,predicate是lambda表達式e -> e.getGender() == Person.Sex.MALE。如果對象e的gender字段的值為Person.Sex.MALE,則返回布爾值true,因此,本例中的filter操作返回一個包含集合roster中所有男性成員的流。
一個終端操作,終端操作(如forEach)生成非流結果,如原始值(如雙精度值)、集合,或者在forEach的情況下,根本沒有值。在本例中,forEach操作的參數是lambda表達式e -> System.out.println(e.getName()),調用對象e上的getName方法(Java運行時和編譯器推斷對象e的類型是Person)。
下面的示例計算集合roster中包含的所有男性成員的平均年齡,其中管道由聚合操作filter、mapToInt和average組成:
double average = roster .stream() .filter(p -> p.getGender() == Person.Sex.MALE) .mapToInt(Person::getAge) .average() .getAsDouble();
mapToInt操作返回一個類型為IntStream的新流(這是一個只包含整數值的流),該操作將其參數中指定的函數應用于特定流中的每個元素,在這個例子中,函數是Person::getAge,它是一個方法引用,返回成員的年齡(或者,你可以使用lambda表達式e -> e. getage())。因此,本例中的mapToInt操作返回一個流,其中包含集合roster中所有男性成員的年齡。
average操作計算類型IntStream中包含的元素的平均值,它返回一個OptionalDouble類型的對象,如果流不包含元素,則average操作返回OptionalDouble的空實例,調用getAsDouble方法將拋出NoSuchElementException。JDK包含許多終端操作,比如average,通過組合流的內容返回一個值,這些操作稱為歸納操作。
聚合操作和迭代器之間的區別像forEach這樣的聚合操作看起來像迭代器,然而,它們有幾個根本的區別:
它們使用內部迭代:聚合操作不包含像next這樣的方法來指示它們處理集合的下一個元素,使用內部委托,應用程序決定迭代什么集合,但是JDK決定如何迭代集合,使用外部迭代,你的應用程序將確定它迭代哪些集合以及如何迭代。然而,外部迭代只能按順序迭代集合的元素,內部迭代沒有這種限制,它可以更容易地利用并行計算,這涉及到將一個問題劃分為子問題,同時解決這些問題,然后將子問題的解的結果組合起來。
它們處理來自流的元素:聚合操作處理流中的元素,而不是直接從集合中聚合,因此,它們也稱為流操作。
它們支持將行為作為參數:可以將lambda表達式指定為大多數聚合操作的參數,這使你能夠自定義特定聚合操作的行為。
上一篇:SortedMap接口文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/75569.html
Java? 教程 Java教程是為JDK 8編寫的,本頁面中描述的示例和實踐沒有利用在后續版本中引入的改進。 Java教程是希望使用Java編程語言創建應用程序的程序員的實用指南,其中包括數百個完整的工作示例和數十個課程,相關課程組被組織成教程。 覆蓋基礎知識的路徑 這些教程以書籍的形式提供,如Java教程,第六版,前往Amazon.com購買。 入門 介紹Java技術和安裝Java開發軟件并使用...
Collection接口 Collection表示一組稱為其元素的對象,Collection接口用于傳遞需要最大通用性的對象集合,例如,按照慣例,所有通用集合實現都有一個帶有Collection參數的構造函數,此構造函數(稱為轉換構造函數)初始化新集合以包含指定集合中的所有元素,無論給定集合的子接口或實現類型如何,換句話說,它允許你轉換集合的類型。 例如,假設你有一個Collection c,它可...
Lambda表達式 匿名類的一個問題是,如果匿名類的實現非常簡單,例如只包含一個方法的接口,那么匿名類的語法可能看起來不實用且不清楚,在這些情況下,你通常會嘗試將功能作為參數傳遞給另一個方法,例如當有人單擊按鈕時應采取的操作,Lambda表達式使你可以執行此操作,將功能視為方法參數,或將代碼視為數據。 上一節匿名類向你展示了如何在不給它命名的情況下實現基類,雖然這通常比命名類更簡潔,但對于只有一個...
集合介紹 本節介紹Java集合框架,在這里,你將了解集合是什么以及它們如何使你的工作更輕松、程序更好,你將了解構成Java集合框架的核心元素 — 接口、實現、聚合操作和算法。 集合 — 有時稱為容器 — 只是一個將多個元素組合到一個單元中的對象,集合用于存儲、檢索、操作和傳遞聚合數據。通常,它們代表形成自然組的數據項,例如撲克牌(卡片集合)、郵件文件夾(信件集合)或電話目錄(名稱到電話號碼的映射)...
摘要:接著我們將數據流按照單詞字段即號索引字段做分組,這里可以簡單地使用方法,得到一個以單詞為的數據流。得到的結果數據流,將每秒輸出一次這秒內每個單詞出現的次數。最后一件事就是將數據流打印到控制臺,并開始執行最后的調用是啟動實際作業所必需的。 本文轉載自 Jark’s Blog ,作者伍翀(云邪),Apache Flink Committer,阿里巴巴高級開發工程師。 本文將從開發環境準備、創建 ...
閱讀 2495·2021-11-24 10:29
閱讀 2634·2021-09-24 09:48
閱讀 5737·2021-09-22 15:56
閱讀 3151·2021-09-06 15:00
閱讀 2667·2019-08-30 15:54
閱讀 740·2019-08-30 13:48
閱讀 2892·2019-08-30 11:17
閱讀 3417·2019-08-29 11:20