樂位元組-Java8新特性-介面預設方法之Stream流(下)

来源:https://www.cnblogs.com/lotbyte/archive/2019/04/10/10686231.html
-Advertisement-
Play Games

接上一篇:《Java8新特性之stream》,下麵繼續接著講Stream 5、流的中間操作 常見的流的中間操作,歸為以下三大類:篩選和切片流操作、元素映射操作、元素排序操作: 5.1、篩選和切片 例如以訂單數據為例,在做報表展示時,會根據訂單狀態、用戶信息、支付結果等狀態來分別展示(即過濾和統計展示 ...


接上一篇:《Java8新特性之stream》,下麵繼續接著講Stream 

 

5、流的中間操作

常見的流的中間操作,歸為以下三大類:篩選和切片流操作、元素映射操作、元素排序操作:

操作描述
篩選和切片 filter(T -> boolean):保留 boolean 為 true 的元素 limit(long n):返回前 n 個元素 skip(long n):去除前 n 個元素 distinct():去除重覆元素,這個方法是通過類的 equals 方法來判斷兩個元素是否相等的
映射 map(T -> R):將流中的每一個元素 T 映射為 R(類似類型轉換) flatMap(T -> Stream<R>): 將流中的每一個元素 T 映射為一個流,再把每一個流連接成為一個流
排序 sorted() / sorted((T, T) -> int):如果流中的元素的類實現了 Comparable 介面,即有自己的排序規則,那麼可以直接調用 sorted() 方法對元素進行排序,如 Stream<Integer>

 

5.1、篩選和切片

例如以訂單數據為例,在做報表展示時,會根據訂單狀態、用戶信息、支付結果等狀態來分別展示(即過濾和統計展示)

定義訂單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);
       List<Order> 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);

5.2、映射

//過濾訂單集合有效訂單  獲取所有訂單訂單編號
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等結果。 對於流的終止操作,分為以下三類:

操作描述
查找與匹配 allMatch:檢查是否匹配所有元素 anyMatch(T -> boolean): 流中是否有一個元素匹配給定的 T -> boolean 條件 noneMatch(T -> boolean): 流中是否沒有元素匹配給定的 T -> boolean 條件 findAny():找到其中一個元素 (使用 stream() 時找到的是第一個元素;使用 parallelStream() 並行時找到的是其中一個元素) findFirst():找到第一個元素 max():返迴流中最大值 min():返迴流中最小值 count():返迴流中元素的總個數
歸約: 將流中元素反覆結合起來,得到一個值 reduce((T, T) -> T) 和 reduce(T, (T, T) -> T): 用於組合流中的元素,如求和,求積,求最大值等
收集: 將流轉換為其他形式,接收一個Collertor介面的實現,用於給Stream中元素做彙總的方法 collect()

 

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());
// 篩選所有有效訂單 返回金額最大訂單值
Optional<Double> max=ordersList.stream().filter((order) -> order.getIsValid() == 1)
  .map(Order::getTotal).max(Double::compare);
System.out.println("訂單金額最大值:"+max.get());
// 篩選所有有效訂單 返回金額最小訂單值
Optional<Double> min=ordersList.stream().filter((order) -> order.getIsValid() == 1)
  .map(Order::getTotal).min(Double::compare);
System.out.println("訂單金額最小值:"+min.get());

6.2、歸約

將流中元素反覆結合起來,得到一個值的操作。

// 歸約操作  計算有效訂單總金額
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<Order> orders= ordersList.stream().filter((order) -> order.getIsValid() == 1).collect(Collectors.toList());
orders.forEach(System.out::println);
// 篩選所有有效訂單 並收集訂單號 與 訂單金額
Map<String,Double> map=ordersList.stream().filter((order) -> order.getIsValid() == 1).
   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<Integer,List<Order>> 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<Integer,Map<String,List<Order>>> 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<Boolean,List<Order>> 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,歡迎關註,轉載請說明出處和作者。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一.項目結構 二.計算模塊和界面模塊間的調用 三.頁面演示效果 四.遇到問題 五.知識點記錄 六.新知識新技能 七.未實現但計劃實現功能 八.學習目標與總結 項目地址:https://git.dev.tencent.com/hey_wuqw/webArithmetic.git 一.項目結構 二. 計 ...
  • 1.前言 匿名內部類在我們JAVA程式員的日常工作中經常要用到,但是很多時候也只是照本宣科地用,雖然也在用,但往往忽略了以下幾點:為什麼能這麼用?匿名內部類的語法是怎樣的?有哪些限制?因此,最近,我在完成了手頭的開發任務後,查閱了一下JAVA官方文檔,將匿名內部類的使用進行了一下總結,案例也摘自官方 ...
  • 註解屬於比較高級的Java開發技術,前面介紹的內置註解專用於編譯器檢查代碼,另外一些註解則由各大框架定義與調用,像Web開發常見的Spring框架、Mybatis框架,Android開發常見的ButterKnife框架等等,都使用了大量的註解。為了更好地弄清註解的應用原理,接下來不妨嘗試自定義註解, ...
  • PIL庫學習及運用 1.庫的介紹Python Imaging Library,簡稱PIL python圖像處理庫,這個庫支持多種文件格式,並提供了強大的圖像處理和圖形處理能力。 下麵是我的學習筆記 首先,先安裝PIL庫,直接打開cmd,輸入pip install pillow,回車即可 這裡先展示一 ...
  • 1.創建項目 組織Django代碼最簡單的方式是使用Django的“項目”(project):一個包含了組成單個網站的所有文件的目錄。Django提供了一個叫django admin.py的命令來幫助創建這樣項目的目錄。 Windows下: 運行之後,我們用資源管理器,可以發現新建了一個mysite ...
  • 配置環境:python 3.6 python編輯器:pycharm 代碼如下: ...
  • docxtpl 按指定的word模板填充內容 安裝 示例 模板文件 目標文件 符《匆匆》朱自清 燕子去了,有再來的時候;楊柳枯了,有再青的時候;桃花謝了,有再開的時候。但是,聰明的,你告訴我,我們的日子為什麼一去不復返呢?——是有人偷了他們罷:那是誰?又藏在何處呢?是他們自己逃走了罷:現在又到了哪裡 ...
  • Python全棧day 02 一、迴圈語句 while 用法 python num = 1 while num not and or 四、編碼補充 gbk碼、gb2312碼:都是亞洲地區使用的編碼,都用2個位元組表示一個漢字。 GBK: 漢字國標擴展碼,基本上採用了原來GB2312 80所有的漢字及碼 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...