lambda 分类聚合_使用Java 8 Lambda,流和聚合
lambda 分類聚合
總覽
在本文中,我們將介紹使用Java 8 lambda,流和聚合來過濾和處理Collection中的對象。 這篇文章中的所有代碼都可以在此處的 BitBucket中找到 。
對于此示例,我們將創建許多對象,這些對象代表我們IT基礎架構中的服務器。 我們將這些對象添加到列表中,然后使用lambda,流和聚合基于某些條件從列表中檢索服務器。
目標
Lambdas
Lambda是Java的一項新功能,允許我們將功能或行為作為參數傳遞給方法。 一個說明Lambda有用性的示例來自UI編碼。 當用戶單擊用戶界面上的按鈕時,通常會導致應用程序中發生某些操作。 在這種情況下,我們確實希望將行為傳遞給onClick(…)方法,以便應用程序將在單擊按鈕時執行給定的行為。 在Java的早期版本中,我們通過將匿名內部類(實現了已知接口)傳遞給方法來實現此目的。 在這種情況下使用的接口通常僅包含一個方法,該方法定義了我們希望傳遞給onClick(…)方法的行為。 盡管這可行,但語法不方便。 匿名內部類仍可用于此目的,但是新的Lambda語法更加簡潔。
綜合運營
當我們使用Collections將對象存儲在程序中時,通常需要做的不僅僅是簡單地將對象放入集合中-我們需要存儲,檢索,刪除和更新這些對象。 聚合操作使用lambda對集合中的對象執行操作。 例如,您可以使用聚合操作來:
- 打印來自特定制造商的庫存中所有服務器的名稱
- 退還清單中早于特定期限的所有服務器
- 計算并返回清單中服務器的平均使用期限(前提是“服務器”對象具有“購買日期”字段)
所有這些任務都可以通過使用聚合操作以及管道和流來完成。 我們將在下面看到這些操作的示例。
管道和流
流水線只是一系列聚合操作。 流是一個項目序列,而不是數據結構,它通過管道從源頭攜帶項目。 管道由以下部分組成:
一些聚合操作(例如forEach)看起來像迭代器,但是它們有根本的區別:
Lambda語法
既然我們已經討論了與Lambda表達式有關的概念,現在該看看它們的語法了。 您可以將Lambda表達式視為匿名方法,因為它們沒有名稱。 Lambda語法包含以下內容:
- 用括號分隔的形式參數的逗號分隔列表。 Lambda表達式中可以省略參數的數據類型。 如果只有一個形式參數,則可以省略括號。
- 箭頭標記:->
- 由單個表達式或代碼塊組成的主體。
使用Lambda,流和聚合操作
如概述中所述,我們將通過過濾和檢索List中的Server對象來演示lambda,流和聚合的用法。 我們來看四個例子:
讓我們開始吧…
服務器類
首先,我們來看一下Server類。 Server類將跟蹤以下內容:
注意(在第65行),我們添加了getServerAge()方法,該方法根據購買日期計算服務器的getServerAge()以年為單位)–在計算服務器中的平均壽命時,將使用此方法庫存。
創建和加載服務器
現在我們有了Server類,我們將創建一個List并加載幾臺服務器:
示例1:打印所有Dell服務器的名稱
對于第一個示例,我們將編寫一些代碼來查找Dell制造的所有服務器,然后將服務器名稱打印到控制臺:
我們的第一步是在第76行–我們必須從服務器列表中獲取流。 一旦有了流,就在第77行添加過濾器中間操作。過濾器操作將服務器流作為輸入,然后生成另一個服務器流,該服務器流僅包含與過濾器lambda中指定的條件匹配的服務器。 我們僅選擇Dell使用以下lambda制造的服務器: s -> s.getManufacturer().equalsIgnoreCase(manufacturer)
變量s表示從流中處理的每個服務器(請記住,我們不必聲明類型)。 箭頭運算符的右側表示我們要為每個處理的服務器評估的語句。 在這種情況下,如果當前服務器的制造商是Dell,我們將返回true,否則返回false。 過濾器產生的輸出流僅包含Dell制造的那些服務器。
最后,我們在第78行上添加了forEach終端操作。forEach操作將服務器流作為輸入,然后在該流中的每個服務器上運行給定的lambda。 我們使用以下lambda將Dell服務器的名稱打印到控制臺: server -> System.out.println(server.getName())
請注意,我們在第一個lambda中使用s作為流中每個服務器的變量名,在第二個lambda中使用server作為變量名-它們不必從一個lambda匹配到下一個lambda。
上面代碼的輸出是我們期望的:
示例2:打印所有超過三年的所有服務器的名稱
我們的第二個示例與第一個示例相似,不同之處在于我們要查找3年以上的服務器:
此示例與第一個示例之間的唯一區別是,我們將過濾器操作(第89行)中的lambda表達式更改為: s -> s.getServerAge() > age
該過濾器的輸出流僅包含3年以上的服務器。
上面代碼的輸出是:
示例3:將所有超過3年的服務器提取到新列表中
我們的第三個示例與第二個示例相似,因為我們正在尋找使用三年以上的服務器。 本示例中的不同之處在于,我們將創建一個僅包含滿足我們條件的服務器的新列表:
與前面的示例一樣,我們從列表中獲取流,并添加過濾器中間操作以創建僅包含3年以上服務器的流(第102和103行)。 現在,在第104行,我們使用collect終端操作而不是forEach終端操作。 collect終端操作將服務器流作為輸入,然后將它們放入參數中指定的數據結構中。 在我們的例子中,我們將流轉換為服務器列表。 結果列表由第100行上聲明的oldServers變量引用。
最后,為了說明在本示例中獲得的服務器與上一個服務器相同,我們在oldServers列表中打印所有服務器的名稱。 請注意,因為我們希望列表中的所有服務器,所以沒有中間過濾器操作。 我們只需從oldServers獲取流,并將其提供給forEach終端操作即可。
輸出是我們期望的:
示例4:計算并打印服務器的平均壽命
在最后一個示例中,我們將計算服務器的平均壽命:
第一步與前面的示例相同–我們從服務器列表中獲取流。 接下來,我們添加mapToLong中間操作。 此聚合操作將服務器流作為輸入,并生成Longs流作為輸出。 根據第119行中指定的lambda將服務器映射到Longs(您也可以在第120行中使用等效語法)。 在這種情況下,我們要抓住每個傳入服務器的年齡,并將其放入生成的Longs流中。
接下來,我們添加平均終端操作。 平均值完全符合您的期望-計算流中所有值的平均值。 諸如平均值之類的終端操作通過對流的內容進行合并或操作來返回一個值,這被稱為歸約操作 。 歸約運算的其他示例包括sum , min , max和count 。
最后,我們添加操作getAsDouble 。 這是必需的,因為平均值返回類型OptionalDouble 。 如果傳入流為空,則average將返回OptionalDouble的空實例。 如果發生這種情況,則調用getAsDouble將拋出NoSuchElementException ,否則它將僅在OptionalDouble實例中返回Double值。
該示例的輸出為:
結論
我們僅涉及到您可以使用lambda,流和聚合進行處理的內容。 我鼓勵您抓住源代碼,使用它,并開始探索這些Java 8新功能的所有可能性。
翻譯自: https://www.javacodegeeks.com/2015/12/using-java-8-lambdas-streams-aggregates.html
lambda 分類聚合
總結
以上是生活随笔為你收集整理的lambda 分类聚合_使用Java 8 Lambda,流和聚合的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jwt令牌_JWT –生成和验证令牌–示
- 下一篇: 黑马2016java_2016年成功的J