摘要:歸約操作計算有效訂單總金額有效訂單總金額收集數據收集將流轉換為其他形式,方法作為終端操作,接收一個接口的實現,用于給中元素做匯總的方法。
接上一篇:《Java8新特性之stream》,下面繼續接著講Stream
5、流的中間操作常見的流的中間操作,歸為以下三大類:篩選和切片流操作、元素映射操作、元素排序操作:
例如以訂單數據為例,在做報表展示時,會根據訂單狀態、用戶信息、支付結果等狀態來分別展示(即過濾和統計展示)
定義訂單Order類
public class Order { // 訂單id private Integer id; // 訂單用戶id private Integer userId; // 訂單編號 private String orderNo; // 訂單日期 private Date orderDate; // 收貨地址 private String address; // 創建時間 private Date createDate; // 更新時間 private Date updateDate; // 訂單狀態 0-未支付 1-已支付 2-代發貨 3-已發貨 4-已接收 5-已完成 private Integer status; // 是否有效 1-有效訂單 0-無效訂單 private Integer isValid; //訂單總金額 private Double total; /** 此處省略getter/setter方法 */ }
測試
public static void main(String[] args) { Order order01 = new Order(1,10,"20190301", new Date(),"上海市-浦東區",new Date(),new Date(),4,1,100.0); Order order02 = new Order(2,30,"20190302", new Date(),"北京市四惠區",new Date(),new Date(),1,1,2000.0); Order order03 = new Order(3,20,"20190303", new Date(),"北京市-朝陽區",new Date(),new Date(),4,1,500.0); Order order04 = new Order(4,40,"20190304", new Date(),"北京市-大興區",new Date(),new Date(),4,0,256.0); Order order05 = new Order(5,40,"20190304", new Date(),"上海市-松江區",new Date(),new Date(),4,0,1000.0); List5.2、映射ordersList= Arrays.asList(order01,order02,order03,order04); // 過濾訂單集合 有效訂單 并打印到控制臺 ordersList.stream().filter((order)->order.getIsValid()==1).forEach(System.out::println); // 過濾訂單集合有效訂單 取前兩條有效訂單 并打印到控制臺 ordersList.stream().filter((order)->order.getIsValid()==1).limit(2).forEach(System.out::println); } // 過濾訂單集合有效訂單 取最后一條記錄 ordersList.stream().filter((order)->order.getIsValid()==1) .skip(ordersList.size()-2).forEach(System.out::println); // 去除訂單編號重復的無效訂單記錄 此時因為比較的為Object Order對象需要重寫HashCode 與Equals 方法 /** * 重寫 equals 方法 * @param obj * @return */ @Override public boolean equals(Object obj) { boolean flag = false; if (obj == null) { return flag; } Order order = (Order) obj; if (this == order) { return true; } else { return (this.orderNo.equals(order.orderNo)); } } /** * 重寫hashcode方法 * @return */ @Override public int hashCode() { int hashno = 7; hashno = 13 * hashno + (orderNo == null ? 0 : orderNo.hashCode()); return hashno; } // 過濾訂單集合無效訂單 去除訂單號重復記錄 ordersList.stream().filter((order)->order.getIsValid()==0).distinct().forEach(System.out::println);
//過濾訂單集合有效訂單 獲取所有訂單訂單編號 ordersList.stream().filter((order)->order.getIsValid()==1).map((order)->order.getOrderNo()).forEach(System.out::println); // 過濾有效訂單 并分離每個訂單下收貨地址市區信息 ordersList.stream().map(o->o.getAddress().split("-")).flatMap(Arrays::stream).forEach(System.out::println);5.3、排序
//過濾有效訂單 并根據用戶id 進行排序 ordersList.stream().filter((order)->order.getIsValid()==1) .sorted((o1,o2)->o1.getUserId()-o2.getUserId()).forEach(System.out::println); //或者等價寫法 ordersList.stream().filter((order)->order.getIsValid()==1) .sorted(Comparator.comparingInt(Order::getUserId)).forEach(System.out::println); // 定制排序規則 /*過濾有效訂單 * 定制排序:如果訂單狀態相同 根據訂單創建時間排序 反之根據訂單狀態排序 */ ordersList.stream().filter((order)->order.getIsValid()==1).sorted((o1,o2)->{ if(o1.getStatus().equals(o2.getStatus())){ return o1.getCreateDate().compareTo(o2.getCreateDate()); }else{ return o1.getStatus().compareTo(o2.getStatus()); }}).forEach(System.out::println);6、流的終止操作
終止操作會從流的流水線生成結果。其結果是任何不是流的值,比如常見的List、 Integer,甚 至void等結果。
對于流的終止操作,分為以下三類:
6.1、查找與匹配// 篩選所有有效訂單 匹配用戶id =20 的所有訂單 System.out.println("allMatch匹配結果:"+ordersList.stream(). filter((order) -> order.getIsValid() == 1).allMatch((o) -> o.getUserId() == 20)); System.out.println("anyMatch匹配結果:"+ordersList.stream(). filter((order) -> order.getIsValid() == 1).anyMatch((o) -> o.getUserId() == 20)); System.out.println("noneMatch匹配結果:"+ordersList.stream(). filter((order) -> order.getIsValid() == 1).noneMatch((o) -> o.getUserId() == 20)); // 篩選所有有效訂單 返回訂單總數 System.out.println("count結果:"+ordersList.stream(). filter((order) -> order.getIsValid() == 1).count()); // 篩選所有有效訂單 返回金額最大訂單值 Optional6.2、歸約max=ordersList.stream().filter((order) -> order.getIsValid() == 1) .map(Order::getTotal).max(Double::compare); System.out.println("訂單金額最大值:"+max.get()); // 篩選所有有效訂單 返回金額最小訂單值 Optional min=ordersList.stream().filter((order) -> order.getIsValid() == 1) .map(Order::getTotal).min(Double::compare); System.out.println("訂單金額最小值:"+min.get());
將流中元素反復結合起來,得到一個值的操作。 // 歸約操作 計算有效訂單總金額 System.out.println("有效訂單總金額:"+ordersList.stream().filter((order) -> order.getIsValid() == 1).map(Order::getTotal).reduce(Double::sum).get());6.3、Collector收集數據
6.3.1、收集
將流轉換為其他形式,coollect 方法作為終端操作, 接收一個Collector接口的實現,用于給Stream中元素做匯總的方法。最常用的方法,把流中所有元素收集到一個 List, Set 或 Collection 中
toList
toSet
toCollection
toMap
// 收集操作
// 篩選所有有效訂單 并收集訂單列表
List
orders.forEach(System.out::println);
// 篩選所有有效訂單 并收集訂單號 與 訂單金額
Map
collect(Collectors.toMap(Order::getOrderNo, Order::getTotal));
// java8 下對map 進行遍歷操作 如果 Map 的 Key 重復了,會報錯
map.forEach((k,v)->{
System.out.println("k:"+k+":v:"+v);
});
6.3.2、匯總
countintg():用于計算總和
count():用于計算總和(推薦使用,寫法更簡潔)
summingInt() ,summingLong(),summingDouble():用于計算總和
averagingInt(),averagingLong(),averagingDouble()用于平均
summarizingInt,summarizingLong,summarizingDouble 同樣可以實現計算總和,平均等操作,比如summarizingInt 結果會返回IntSummaryStatistics 類型 ,然后通過get方法獲取對應匯總值即可
// 匯總操作
//篩選所有有效訂單 返回訂單總數
System.out.println("count結果:"+ordersList.stream().
filter((order) -> order.getIsValid() == 1).collect(Collectors.counting()));
System.out.println("count結果:"+ordersList.stream().
filter((order) -> order.getIsValid() == 1).count());
// 返回訂單總金額
System.out.println("訂單總金額:"+ordersList.stream().
filter((order) -> order.getIsValid() == 1).collect(Collectors.summarizingDouble(Order::getTotal)));
System.out.println("訂單總金額:"+ordersList.stream().
filter((order) -> order.getIsValid() == 1).mapToDouble(Order::getTotal).sum());
System.out.println("訂單總金額:"+ordersList.stream().
filter((order) -> order.getIsValid() == 1).map(Order::getTotal).reduce(Double::sum).get());
// 返回 用戶id=20 有效訂單平均每筆消息金額
System.out.println("用戶id=20 有效訂單平均每筆消費金額:"+ordersList.stream().
filter((order) -> order.getIsValid() == 1). filter((order -> order.getUserId()==20)) .collect(Collectors.averagingDouble(Order::getTotal)));
System.out.println("用戶id=20 有效訂單平均每筆消費金額:"+
ordersList.stream(). filter((order) -> order.getIsValid() == 1). filter((order -> order.getUserId()==20)) .mapToDouble(Order::getTotal).average().getAsDouble());
System.out.println("用戶id=20 有效訂單平均每筆消費金額:"+
ordersList.stream(). filter((order) -> order.getIsValid() == 1). filter((order -> order.getUserId()==20)) .collect(Collectors.summarizingDouble(Order::getTotal)).getAverage());
// 篩選所有有效訂單 并計算訂單總金額
System.out.println("訂單總金額:"+ordersList.stream().filter((order) -> order.getIsValid() == 1)
.collect(Collectors.summingDouble(Order::getTotal)));
// 篩選所有有效訂單 并計算最小訂單金額
System.out.println("最小訂單金額:"+ordersList.stream().filter((order) -> order.getIsValid() == 1)
.map(Order::getTotal).collect(Collectors.minBy(Double::compare)));
// 篩選所有有效訂單 并計算最大訂單金額
System.out.println("最大訂單金額:"+ordersList.stream().filter((order) -> order.getIsValid() == 1)
.map(Order::getTotal).collect(Collectors.maxBy(Double::compare)));
6.3.3、最值
maxBy,minBy 兩個方法,需要一個 Comparator 接口作為參數,實現最大 最小值獲取操作 // 取最會 // 篩選所有有效訂單 并計算最小訂單金額 System.out.println("最小訂單金額:"+ordersList.stream().filter((order) -> order.getIsValid() == 1) .map(Order::getTotal).collect(Collectors.minBy(Double::compare))); // 篩選所有有效訂單 并計算最大訂單金額 System.out.println("最大訂單金額:"+ordersList.stream().filter((order) -> order.getIsValid() == 1) .map(Order::getTotal).collect(Collectors.maxBy(Double::compare)));
6.3.4、分組
groupingBy 用于將數據分組,最終返回一個 Map 類型
groupingBy 可以接受一個第二參數實現多級分組
// 分組-根據有效訂單支付狀態進行分組操作 Map> g01=ordersList.stream().filter((order) -> order.getIsValid() == 1) .collect(Collectors.groupingBy(Order::getStatus)); g01.forEach((status,order)->{ System.out.println("----------------"); System.out.println("訂單狀態:"+status); order.forEach(System.out::println); }); // 分組-查詢有效訂單 根據用戶id 和 支付狀態進行分組 Map >> g02= ordersList.stream().filter((order) -> order.getIsValid() == 1) .collect(Collectors.groupingBy(Order::getUserId,Collectors.groupingBy((o)->{ if(o.getStatus()==0){ return "未支付"; }else if (o.getStatus()==1){ return "已支付"; }else if (o.getStatus()==2){ return "待發貨"; }else if (o.getStatus()==3){ return "已發貨"; }else if (o.getStatus()==4){ return "已接收"; } else{ return "已完成"; } }))); g02.forEach((userId,m)->{ System.out.println("用戶id:"+userId+"-->有效訂單如下:"); m.forEach((status,os)->{ System.out.println("狀態:"+status+"---訂單列表如下:"); os.forEach(System.out::println); }); System.out.println("-----------------------"); });
6.3.5、partitioningBy 分區
分區與分組的區別在于,分區是按照 true 和 false 來分的,因此partitioningBy 接受的參數的 lambda 也是?T -> boolean // 分區操作 篩選訂單金額>1000 的有效訂單 Map> g03= ordersList.stream().filter((order) -> order.getIsValid() == 1) .collect(Collectors.partitioningBy((o)->o.getTotal()>1000)); g03.forEach((b,os)->{ System.out.println("分區結果:"+b+"--列表結果:"); os.forEach(System.out::println); }); // 拼接操作 篩選有效訂單 并進行拼接 String orderStr=ordersList.stream().filter((order) -> order.getIsValid() == 1).map(Order::getOrderNo) .collect(Collectors.joining(",")); System.out.println(orderStr);
樂字節-Java新特性之stream流就介紹到這里了,接下來小樂還會接著給大家講解Java8新特性之Optional,歡迎關注,轉載請說明出處和作者。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/77518.html
摘要:需要注意的是很多流操作本身就會返回一個流,所以多個操作可以直接連接起來,如下圖這樣,操作可以進行鏈式調用,并且并行流還可以實現數據流并行處理操作。為集合創建并行流。 上一篇文章,小樂給大家介紹了《Java8新特性之方法引用》,下面接下來小樂將會給大家介紹Java8新特性之Stream,稱之為流,本篇文章為上半部分。 1、什么是流? Java Se中對于流的操作有輸入輸出IO流,而Jav...
摘要:大家好,我是樂字節的小樂。需要注意的是很多流操作本身就會返回一個流,所以多個操作可以直接連接起來,如下圖這樣,操作可以進行鏈式調用,并且并行流還可以實現數據流并行處理操作。為集合創建并行流。 大家好,我是樂字節的小樂。說起流,我們會聯想到手機、電腦組裝流水線,物流倉庫商品包裝流水線等等,如果把手機 ,電腦,包裹看做最終結果的話,那么加工商品前的各種零部件就可以看做數據源,而中間一系列的...
摘要:語法中接口可以包含實現方法,需要使用修飾,此類方法稱為默認方法。核心特性接口默認方法就介紹到這里了,后續小樂會繼續講述核心特性。 JAVA8已經發布很久,是自java5(2004年發布)之后Oracle發布的最重要的一個版本。其中包括語言、編譯器、庫、工具和JVM等諸多方面的新特性,對于國內外互聯網公司來說,Java8是以后技術開發的趨勢。這里主要講解在開發中幾個核心的新特性。(主要從...
摘要:大家好,上一篇小樂給大家講述了樂字節核心特性表達式,點擊回顧。接下來繼續核心特性之函數式接口。感謝大家欣賞小樂帶來的核心特性之函數式接口,接下來還會更多核心技術講解,請關注樂字節如需要視頻課程,請搜索樂字節騰訊課堂 大家好,上一篇小樂給大家講述了《樂字節-Java8核心特性-Lambda表達式》,點擊回顧。接下來繼續:Java8核心特性之函數式接口。 什么時候可以使用Lambda?通常...
摘要:大家好啊,上次小樂給大家介紹了最最重要的一個特性流,點擊可以回顧哦。并且可以避免空指針異常。這種操作對于參數判斷提供很大便利,例如參數滿足指定條件的后續操作查詢操作字符串拼接,常見的處理多請求頁面轉發處理等操作。 大家好啊,上次小樂給大家介紹了Java8最最重要的一個特性——Stream流,點擊可以回顧哦。 Optional類(java.util.Optional)是一個容器類,代表一...
閱讀 4693·2021-11-18 13:23
閱讀 896·2021-09-22 15:24
閱讀 1920·2021-09-06 15:00
閱讀 2618·2021-09-03 10:30
閱讀 1277·2021-09-02 15:15
閱讀 2055·2019-08-30 15:54
閱讀 3029·2019-08-30 15:44
閱讀 1449·2019-08-29 15:12