java 流式_Java開發筆記(七十二)Java8新增的流式處理

通過前面幾篇文章的學習,大家應能掌握幾種容器類型的常見用法,對于簡單的增刪改和遍歷操作,各容器實例都提供了相應的處理方法,對于實際開發中頻繁使用的清單List,還能利用Arrays工具的asList方法給清單對象做初始化賦值,另外提供了專門的Collections工具進行排序、求最大元素、求最小元素等操作。那么涉及到更加復雜的數據處理,游蕩如何有針對性地篩選和進一步加功能?

依次遍歷目標容器,對所有元素逐個加以分析判斷,并酌情將具體數據調整至滿意的狀態,這種千篇一律的業務流程固然能夠解決問題,可惜由此帶來的副作用是顯而易見的,包括但不限于:代碼冗長、分支眾多、邏輯繁瑣、不易重用等等。為了改進相關業務邏輯的編程方式,幫助開發者形成良好的編碼風格,Java的每次版本更新都試圖給出有效的解決方案,其中影響深遠的當數Java8推出的兩項新特性:新增的泛型接口與流式處理。關于前一個泛型接口特性,用于容器操作的泛型接口主要有三個,分別是斷言接口、消費接口和函數接口,有關的應用案例可參見之前的泛型接口文章,這里不再贅述。真正具有革命性意義的才是本文的主角——流式處理。

所謂流,隱含著流水線的意思,也就是由開發者事先設定一批處理指令,說明清楚每條指令的前因后果,然后啟動流水線作業,即可得到最終的處理結果。流式處理的精髓在于一氣呵成,只要萬事俱備,決不拖泥帶水。開展流式處理主要包括三個步驟:獲得容器的流對象、設置流的各項篩選和加工指令,以及規劃處理結果的展示形式。下面就分別予以詳細介紹。

1、獲得容器的流對象

Java8給每種容器都準備了兩條流水線,一條是串行流,另一條是并行流。串行流顧名思義各項任務是前后串在一起的,只有處理完前一項任務,才能繼續執行后一項任務。調用容器實例的stream方法即可獲得該容器的串行流對象,而調用容器實例的parallelStream方法可獲得該容器的并行流對象。

流對象的獲取操作同時也是流式處理的開始指令,每次進行流式處理之前,都必須先獲取當前容器的流對象,要么獲取串行流,要么獲取并行流。

2、設置流的各項篩選和加工指令

不管是串行流還是并行流,它們承載的都是容器內部的原始數據,這些原材料要經過各道加工工序,之后才會得到具備初步形態的半成品。加工數據期間所調用的流方法說明如下:

filter:按照指定條件過濾。即篩選出符合條件的那部分數據。

sorted:根據指定字段對所有記錄排序。可選擇升序或者降序。

map:映射成指定的數據類型。

limit:只取前面若干條數據。

distinct:去掉重復記錄。保證每條記錄都是唯一的。

以上的加工方法屬于流式處理的中間指令,每次流水線作業都允許設置一條或者多條中間指令。

3、規劃處理結果的展示形式

前一步的各項加工處理完畢,還要弄個包裝才能輸出最終的成品,也就是這條流水線生產出來的數據到底長什么模樣。結果數據的記錄包裝有三種形式,分別對應如下的三個方法:

count:統計結果數據的數量。

forEach:依次遍歷結果數據,并逐條進行個性化處理。

collect:搜集和整理結果數據,并返回指定格式的清單記錄。

上面的三個包裝方法屬于流式處理的結束指令,每次流水線作業必須配備有且僅有其中的一條結束指令。

接下來列舉幾個實際應用的業務場景,看看采取流式處理時該如何編碼。首先準備一個原始的蘋果清單,后續將對這個蘋果清單發動流水作業。原始清單的獲取代碼示例如下:

// 獲取默認的蘋果清單

private static ArrayList getAppleList() {

ArrayList appleList = new ArrayList();

appleList.add(new Apple("紅蘋果", "RED", 150d, 10d));

appleList.add(new Apple("大蘋果", "green", 250d, 10d));

appleList.add(new Apple("紅蘋果", "red", 300d, 10d));

appleList.add(new Apple("大蘋果", "yellow", 200d, 10d));

appleList.add(new Apple("紅蘋果", "green", 100d, 10d));

appleList.add(new Apple("大蘋果", "Red", 250d, 10d));

return appleList;

}

然后需要統計紅蘋果總數的話,可通過下列的流式代碼開展統計操作:

// 統計紅蘋果的總數

long redCount = getAppleList().stream() // 串行處理

.filter(Apple::isRedApple) // 過濾條件。專門挑選紅蘋果

.count(); // 統計記錄個數

System.out.println("紅蘋果總數=" + redCount);

注意到上述代碼的filter方法內部出現了方法引用,的確流式處理的主要方法都預留了函數式接口的調用,所以經常會在流式代碼中看到五花八門的方法引用與Lambda表達式。比如下面的結果遍歷代碼就在forEach方法中填充了Lambda表達式:

// 對每個紅蘋果依次進行處理

getAppleList().stream() // 串行處理

.filter(Apple::isRedApple) // 過濾條件。專門挑選紅蘋果

.forEach(s -> System.out.println("當前顏色為"+s.getColor())); // 逐條開展操作

當然流水作業更常見的輸出另一串清單數據,此時流式處理的結束指令就得采用collect方法。下面便是從原始清單中挑出紅蘋果清單的流式代碼:

// 挑出紅蘋果清單

List redAppleList = getAppleList().stream() // 串行處理

//.parallelStream() // 并行處理

.filter(Apple::isRedApple) // 過濾條件。專門挑選紅蘋果

.sorted(Comparator.comparing(Apple::getWeight)) // 按蘋果重量升序排列

//.sorted(Comparator.comparing(Apple::getWeight).reversed()) // 按蘋果重量降序排列

.limit(3) // 只取前幾條數據

.distinct() // 去掉重復記錄

.collect(Collectors.toList()); // 返回一串清單

System.out.println("紅蘋果清單=" + redAppleList.toString());

結果清單可能不需要完整的蘋果信息,只需列出蘋果名稱字段,那么得調用map方法把完整的蘋果信息映射為單個的名稱字段。此時的篩選代碼變成下面這樣:

// 挑出去重后的蘋果名稱清單

List allNameList = getAppleList().stream() // 串行處理

.map(Apple::getName) // 映射成新的數據類型

.distinct() // 去掉重復記錄

.collect(Collectors.toList()); // 返回一串清單

System.out.println("蘋果名稱去重后的清單=" + allNameList.toString());

除了普通的清單,collect方法還能返回分組清單,也就是把結果數據按照某種條件進行分組,再統計每個分組的成員數目。仍以蘋果清單為例,紅蘋果可通過名稱或者產地分組,分組的同時計算每個小組里各有多少粒蘋果。于是形成了以下的分組計數代碼:

// 按照名稱統計紅蘋果的分組個數

Map redStatisticCount = getAppleList().stream() // 串行處理

.filter(Apple::isRedApple) // 過濾條件。專門挑選紅蘋果

.collect(Collectors.groupingBy(Apple::getName, Collectors.counting())); // 返回分組計數

System.out.println("紅蘋果分組計數=" + redStatisticCount.toString());

分組計數僅僅是簡單統計各組的成員數量,有時還想單獨計算某個字段的統計值,比如每個小組里的蘋果總價各是多少?這時collect方法必須同時完成兩項任務,第一項要根據某種條件分組,第二項要對各組的蘋果價格求和,如此改造之后的分組求和代碼如下所示:

// 按照名稱統計紅蘋果的分組總價

Map redPriceSum = getAppleList().stream() // 串行處理

.filter(Apple::isRedApple) // 過濾條件。專門挑選紅蘋果

.collect(Collectors.groupingBy(Apple::getName, Collectors.summingDouble(Apple::getPrice))); // 返回分組并對某字段求和

System.out.println("紅蘋果分組總價=" + redPriceSum.toString());

觀察以上的具體案例,發現流式處理的代碼相當連貫,每個步驟該做什么事情都一清二楚,中間沒有許多繁復的流程控制,唯有一條條分工明確的處理指令,同時充分發揮了方法引用及Lambda表達式的便利性,使得原本令人頭痛的容器加工變成了有章可循的流水線作業,從而極大地提高了開發者的編碼效率。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/534620.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/534620.shtml
英文地址,請注明出處:http://en.pswp.cn/news/534620.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java保留二位小數_java使double保留兩位小數的多方法 java保留兩位小數

復制代碼代碼如下:mport java.text.DecimalFormat;DecimalFormat df new DecimalFormat("######0.00");double d1 3.23456double d2 0.0;double d3 2.0;df.format(d1);df.format(d2);df.format(d3);3個結果分別為:復制代碼代碼如下:3.230.002.00java保留兩位…

linux java jar打包_【Java】Java程序打包成jar包在Linux上運行

當需要把在Windows上開發的Java程序用在Linux上運行時,就需要吧該Java程序打包成jar包上傳到Linux上去運行。1.Java程序用MyEclipse打包成可運行的jar包(1)在MyEclipse中選中需要打包的項目,點擊右鍵,選擇:Export... 如下圖所示&a…

java匿名對象 回收_Java 匿名對象

我們知道一般實例化一個對象的格式,如下:Car car new Car();其中,變量名 car 就是 new Car() 這個對象的名字。car 是引用類型的變量,它的值存放的是對象的引用(或地址),通過 car 這個變量我們就可以間接使用對象。那…

java int 正則表達式_java正則表達式

Java正則表達式正則表達式定義了字符串的模式。正則表達式可以用來搜索、編輯或處理文本。正則表達式并不僅限于某一種語言,但是在每種語言中有細微的差別。Java正則表達式和Perl的是最為相似的。java.util.regex包主要包括以下三個類:Pattern類&#xf…

mysql.h 動態編譯命令_Linux環境編譯動態庫和靜態庫總結

對Linux環境動態庫和靜態庫的一些基礎知識做一些總結,首先總結靜態庫的編譯步驟。1 先基于.cpp或者.c文件生成對應的.o文件2將幾個.o文件 使用ar -cr命令 生成libname.a文件libname.a 為靜態庫, name 為靜態庫的名字,可以根據模塊功能命名。舉…

netbeans java中文_Ubuntu?下jdk安裝中文字體?java?解決netbeans?方塊字?中文亂碼

安裝環境Ubuntu 11.04、javajdk1.6.0_27首先找到你需要的字體,比如我就是從windows系統里拷出來的,C:\WINDOWS\Fonts這里有很多字體,我只拷貝了simsun.ttc(中文 宋體,從xp系統拷貝的,win7 下沒有這個文件)安裝java后&a…

python 教學_「Python基礎」一次就裝好Python手把手裝到好

一、前言:安裝Python有兩個主要的方法,視情況而定我兩個都會用:(1)安裝 AnacondaAnaconda像一個懶人包,安裝它等于把Python安裝好連同把Python大部分的套件也下載好了,不只如此連通較常用的Python IDE一同幫你裝到好。…

java求二維數組每行的最大值_用JAVA輸入一個二維數組a[3][4]的元素值,求輸出其元素最大值...

展開全部這個簡單啊,把所有元素遍歷一邊62616964757a686964616fe58685e5aeb931333335343963代碼:import java.util.Scanner;public class Help2 {public static void main(String[] args) {Scanner inputnew Scanner(System.in);System.out.print("…

java redis 面試題_Java開發人員怎么面試 常見Redis面試題有哪些

Java開發人員怎么面試?常見Redis面試題有哪些?Redis是目前各大企業都在使用的人們技術,也是企業選拔人才時考核的一個難題。有很多同學只是簡單了解Redis的應用,但對于為什么要用Redis以及企業面試中有關Redis的問題卻答不上來。接…

java方法重載實事例_零基礎java入門教程函數重載function實例化格式案例

java函數的重載,說白了就是函數塊函數名一樣,但函數類型和參數類型和參數列表個數不同重載之和參數列表有關系,與返回值無關java函數重載函數重載鋪墊如下圖函數重載鋪墊上圖功能顯示,功能一致所以功能一致所以用的功能函數名一致…

java 類 屬性數量_跟我學java編程—Java類的屬性與成員變量

在定義類時,經常需要抽象出它的屬性,并定義在類的主體中。下面就來介紹與屬性相關的內容。常量屬性在類中定義的屬性有常量屬性和成員屬性之分。常量屬性用final關鍵字修飾,常量只能賦值一次,在程序中不能修改它的值。一般來說&am…

java獲取界面輸入數字_通過JAVA設計 GUI 界面的計算器程序,用戶可以通過鼠標依次輸入參加計算的數值,進行加、減、乘、...

通過JAVA設計 GUI 界面的計算器程序,用戶可以通過鼠標依次輸入參加計算的數值,進行加、減、乘、2016-08-22 0 0 0 4.0分其他1積分下載如何獲取積分?通過JAVA設計 GUI 界面的計算器程序,用戶可以通過鼠標依次輸入參加計算的數值&am…

java自定義錯誤碼類_如何編寫和應用Java的自定義異常類

11.7.1編寫自定義異常類的模式編寫自定義異常類實際上是繼承一個API標準異常類,用新定義的異常處理信息覆蓋原有信息的過程。常用的編寫自定義異常類的模式如下:public class CustomException extends Exception {//或者繼承任何標準異常類public Custom…

java對mysql查詢_如何利用java對mysql數據庫進行增刪改查

代碼如下:增:Test//數據插入public void demo1() {Connection connnull;Statement stmtnull;try {//注冊驅動Class.forName("com.mysql.jdbc.Driver");//創建連接connDriverManager.getConnection("jdbc:mysql://localhost:3306/name&quo…

util.java_TelnetUtil.java

package com.ailk.ess.webapp2.servermng.net;import java.io.InputStream;import java.io.OutputStream;import java.util.ArrayList;import java.util.List;import org.apache.commons.net.telnet.TelnetClient;public class TelnetUtil {//telnet客戶端對象VT220/VT52Telnet…

生活中java繼承例子_簡單繼承例子:java

通用類,來繼承出圓和矩形。package circle;public class Geometric {private String color"white";private boolean filled;private java.util.Date dateCreated;public Geometric(){dateCreatednew java.util.Date();}public Geometric(String color,boo…

java技術簡介英文_Java技術常見的英文縮寫

1、 URL,Uniform Resource Location,統一資源定位符。2、 JDBC,Java DataBase Connectivity,Java數據庫連接。3、 JSP,Java Server Pages,Java服務器頁面。4、 JVM,Java Virtual Machine&#x…

Java解決空引用_Java 匠人手法 - 優雅的處理空值

原標題:Java 匠人手法 - 優雅的處理空值作者:Lrwin導語在筆者幾年的開發經驗中,經常看到項目中存在到處空值判斷的情況,這些判斷,會讓人覺得摸不這頭緒,它的出現很有可能和當前的業務邏輯并沒有關系。但它會…

mysql 嘗試讀取超過流末尾的_MySql異常:嘗試讀取超出流末尾的內容

問題詳細描述:2020-09-04 11:28:19,576 [DefaultQuartzScheduler_Worker-1] DEBUG MySql.Data.MySqlClient.MySqlException (0x80004005): Fatal error encountered during command execution. ---> MySql.Data.MySqlClient.MySqlException (0x80004005): Fatal …

mysql對稱連接什么意思_對稱加密與非對稱加密的區別是什么

區別:1、對稱加密中加密和解密使用的秘鑰是同一個;非對稱加密中采用兩個密鑰,一般使用公鑰進行加密,私鑰進行解密。2、對稱加密解密的速度比較快,非對稱加密和解密花費的時間長、速度相對較慢。3、對稱加密的安全性相對…