樂位元組-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
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...