流的概念
Java Se中對(duì)于流的操作有輸入輸出IO流,而Java8中引入的Stream 屬于Java API中的一個(gè)新成員,它允許你以聲明性方式處理數(shù)據(jù)集合,Stream 使用一種類似 SQL 語(yǔ)句從數(shù)據(jù)庫(kù)查詢數(shù)據(jù)的直觀方式來(lái)提供一種對(duì) Java 集合運(yùn)算和表達(dá)的高階抽象熙涤。 注意這里的流操作可以看做是對(duì)集合數(shù)據(jù)的處理鸳慈。
簡(jiǎn)單來(lái)說(shuō),流是一種數(shù)據(jù)渠道,用于操作數(shù)據(jù)源(集合、數(shù)組遏匆、文件等)所生產(chǎn)的元素序列痪署。
源-流會(huì)使用一個(gè)提供數(shù)據(jù)的源,如集合码泞、數(shù)組或輸入|輸出資源。
從有序集生成流時(shí)會(huì)保留原有的順序狼犯。由列表生成的流余寥,其元素順序與列表一致
元素序列-就像集合一樣,流也提供了一個(gè)接口,可以訪問(wèn)特定元素類型的一組有序值悯森。
數(shù)據(jù)處理操作-流的數(shù)據(jù)處理功能支持類似于數(shù)據(jù)庫(kù)的操作(數(shù)據(jù)篩選宋舷、過(guò)濾、排序等操作)瓢姻。
流水線-多個(gè)流操作本身會(huì)返回一個(gè)流祝蝠,多個(gè)操作就可以鏈接起來(lái),成為數(shù)據(jù)處理的一道流水線。
流&集合
計(jì)算的時(shí)期
集合中數(shù)據(jù)都是計(jì)算完畢的數(shù)據(jù)幻碱,例如從數(shù)據(jù)庫(kù)中查詢用戶記錄 按用戶id 查詢 降序排列 然后通過(guò)list 接收用戶記錄绎狭,數(shù)據(jù)的計(jì)算已在放入集合前完成。
流中數(shù)據(jù)按需計(jì)算褥傍,按照使用者的需要計(jì)算數(shù)據(jù)儡嘶,例如通過(guò)搜索引擎進(jìn)行搜索,搜索出來(lái)的條目并不是全部呈現(xiàn)出來(lái)的恍风,而且先顯示最符合的前 10 條或者前 20 條蹦狂,只有在點(diǎn)擊 “下一頁(yè)” 的時(shí)候,才會(huì)再輸出新的 10 條邻耕。流的計(jì)算也是這樣鸥咖,當(dāng)用戶需要對(duì)應(yīng)數(shù)據(jù)時(shí)燕鸽,Stream 才會(huì)對(duì)其進(jìn)行計(jì)算處理兄世。
外部迭代與內(nèi)部迭代
把集合比作一個(gè)工廠的倉(cāng)庫(kù)的話,一開(kāi)始工廠硬件比較落后啊研,要對(duì)貨物作什么修改御滩,此時(shí)工人親自走進(jìn)倉(cāng)庫(kù)對(duì)貨物進(jìn)行處理,有時(shí)候還要將處理后的貨物轉(zhuǎn)運(yùn)到另一個(gè)倉(cāng)庫(kù)中党远。此時(shí)對(duì)于開(kāi)發(fā)者來(lái)說(shuō)需要親自去做迭代削解,一個(gè)個(gè)地找到需要的貨物,并進(jìn)行處理沟娱,這叫做外部迭代氛驮。
當(dāng)工廠發(fā)展起來(lái)后,配備了流水線作業(yè)济似,工廠只要根據(jù)需求設(shè)計(jì)出相應(yīng)的流水線矫废,然后工人只要把貨物放到流水線上盏缤,就可以等著接收成果了,而且流水線還可以根據(jù)要求直接把貨物輸送到相應(yīng)的倉(cāng)庫(kù)蓖扑。
這就叫做內(nèi)部迭代唉铜,流水線已經(jīng)幫你把迭代給完成了,你只需要說(shuō)要干什么就可以了(即設(shè)計(jì)出合理的流水線)律杠。相當(dāng)于 Java8 引入的Stream 對(duì)數(shù)據(jù)的處理實(shí)現(xiàn)了”自動(dòng)化”操作潭流。
流操作過(guò)程
整個(gè)流操作就是一條流水線,將元素放在流水線上一個(gè)個(gè)地進(jìn)行處理柜去。需要注意的是:很多流操作本身就會(huì)返回一個(gè)流灰嫉,所以多個(gè)操作可以直接連接起來(lái), 如下圖這樣嗓奢,操作可以進(jìn)行鏈?zhǔn)秸{(diào)用熬甫,并且并行流還可以實(shí)現(xiàn)數(shù)據(jù)流并行處理操作。
總的來(lái)說(shuō)蔓罚,流操作過(guò)程分為三個(gè)階段:
創(chuàng)建
借助數(shù)據(jù)源創(chuàng)建流對(duì)象
中間處理
篩選椿肩、切片、映射豺谈、排序等中間操作
終止流
匹配郑象、匯總、分組等終止操作
流的創(chuàng)建
對(duì)流操作首先要?jiǎng)?chuàng)建對(duì)應(yīng)的流茬末,流的創(chuàng)建集中形式如下:
1 集合創(chuàng)建流
在 Java 8 中, 集合接口有兩個(gè)方法來(lái)生成流:
stream() ? 為集合創(chuàng)建串行流厂榛。
parallelStream() ? 為集合創(chuàng)建并行流。
示例代碼如下:
public static void main(String[] args) { ? ?/** ? ? ? ? * 定義集合l1 并為集合創(chuàng)建串行流 ? ? ? ? */ ? ?List<String> l1 = Arrays.asList("周星馳", "周杰倫", "周星星", "周潤(rùn)發(fā)"); ? ?// 返回串行流 ? ?l1.stream(); ? ?// 返回并行流 ? ?l1.parallelStream(); }
上述操作得到的流是通過(guò)原始數(shù)據(jù)轉(zhuǎn)換過(guò)來(lái)的流丽惭,除了這種流創(chuàng)建的基本操作外击奶,對(duì)于流的創(chuàng)建還有以下幾種方式。
2 值創(chuàng)建流
Stream.of(T...) : Stream.of("aa", "bb") 生成流
//值創(chuàng)建流 生成一個(gè)字符串流Stream<String> stream = Stream.of("java8", "Spring", "SpringCloud"); stream.forEach(System.out::println);3 數(shù)組創(chuàng)建流
根據(jù)參數(shù)的數(shù)組類型創(chuàng)建對(duì)應(yīng)的流责掏。
Arrays.stream(T[ ])
Arrays.stream(int[ ])
Arrays.stream(double[ ])
Arrays.stream(long[ ])
/** * 這里以int 為例 ? long double 不再舉例 */ Stream stream = Arrays.stream(Arrays.asList(10, 20, 30, 40).toArray()); // 根據(jù)數(shù)組索引范圍創(chuàng)建指定Stream stream = Arrays.stream(Arrays.asList(10, 20, 30, 40).toArray(), 0, 2);4 文件生成流stream = Files.lines(Paths.get("C:\\java\\jdbc.properties")); System.out.println(stream.collect(Collectors.toList()));// 指定字符集編碼stream = Files.lines(Paths.get("C:\\java\\jdbc.properties"), Charset.forName("utf-8")); System.out.println(stream.collect(Collectors.toList()));5 函數(shù)生成流
兩個(gè)方法:
iterate : 依次對(duì)每個(gè)新生成的值應(yīng)用函數(shù)
generate :接受一個(gè)函數(shù)柜砾,生成一個(gè)新的值
// 重100 開(kāi)始 生成偶數(shù)流 Stream.iterate(100, n -> n + 2); // 產(chǎn)生1-100 隨機(jī)數(shù) Stream.generate(() ->(int) (Math.random() * 100 + 1));流中間操作
流的中間操作分為三大類:篩選切片、映射换衬、排序痰驱。
篩選切片:類似sql 中where 條件判斷的意思,對(duì)元素進(jìn)行篩選操作
映射:對(duì)元素結(jié)果進(jìn)行轉(zhuǎn)換 瞳浦,優(yōu)點(diǎn)類似select 字段意思或者對(duì)元素內(nèi)容進(jìn)行轉(zhuǎn)換處理
排序:比較好理解 担映,常用sql 中按字段升序 降序操作
?
流中間操作數(shù)據(jù)準(zhǔn)備(這里以訂單數(shù)據(jù)處理為例)
@Datapublic class Order { ? ?// 訂單id ? ?private Integer id; ? ?// 訂單用戶id ? ?private Integer userId; ? ?// 訂單編號(hào) ? ?private String orderNo; ? ?// 訂單日期 ? ?private Date orderDate; ? ?// 收貨地址 ? ?private String address; ? ?// 創(chuàng)建時(shí)間 ? ?private Date createDate; ? ?// 更新時(shí)間 ? ?private Date updateDate; ? ?// 訂單狀態(tài) ?0-未支付 ?1-已支付 ?2-待發(fā)貨 ?3-已發(fā)貨 ?4-已接收 ?5-已完成 ? ?private Integer status; ? ?// 是否有效 ?1-有效訂單 ?0-無(wú)效訂單 ? ?private Integer isValid; ? ?//訂單總金額 ? ?private ?Double total; ?} Order order01 = new Order(1, 10, "20190301", ? ? ? ? ? ? ? ?new Date(), "上海市-浦東區(qū)", new Date(), new Date(), 4, 1, 100.0); Order order02 = new Order(2, 30, "20190302", ? ? ? ? ? ? ? ? ? ?new Date(), "北京市四惠區(qū)", new Date(), new Date(), 1, 1, 2000.0); Order order03 = new Order(3, 20, "20190303", ? ? ? ? ? ? ? ? ? ?new Date(), "北京市-朝陽(yáng)區(qū)", new Date(), new Date(), 4, 1, 500.0); Order order04 = new Order(4, 40, "20190304", ? ? ? ? ? ? ? ? ? ?new Date(), "北京市-大興區(qū)", new Date(), new Date(), 4, 1, 256.0); Order order05 = new Order(5, 40, "20190304", ? ? ? ? ? ? ? ? ? ?new Date(), "上海市-松江區(qū)", new Date(), new Date(), 4, 1, 1000.0); ordersList = Arrays.asList(order01, order02, order03, order04, order05);篩選&切片
篩選有效訂單
// 過(guò)濾有效訂單ordersList.stream().filter((order) -> order.getIsValid() == 1) ? ?.forEach(System.out::println);
篩選有效訂單 取第一頁(yè)數(shù)據(jù)(每頁(yè)2條記錄)
// 過(guò)濾有效訂單 取第一頁(yè)數(shù)據(jù)(每頁(yè)2條記錄) ordersList.stream().filter((order) -> order.getIsValid() == 1) ? ? .limit(2) ? ? .forEach(System.out::println);
篩選訂單集合有效訂單 取最后一條記錄
// 過(guò)濾訂單集合有效訂單 取最后一條記錄ordersList.stream().filter((order) -> order.getIsValid() == 1) ? ?.skip(ordersList.size() - 2) ?// 跳過(guò)前ordersList.size()-2 記錄 ? ?.forEach(System.out::println);
篩選有效訂單 取第3頁(yè)數(shù)據(jù)(每頁(yè)2條記錄)
// 過(guò)濾有效訂單 取第3頁(yè)數(shù)據(jù)(每頁(yè)2條記錄) 并打印到控制臺(tái)ordersList.stream().filter((order) -> order.getIsValid() == 1) ? ?.skip((3 - 1) * 2) ? ?.limit(2) ? ?.forEach(System.out::println);
篩選無(wú)效訂單去除重復(fù)訂單號(hào)記錄
// 過(guò)濾無(wú)效訂單 去除重復(fù)訂單號(hào)記錄 ?重寫(xiě)Order equals 與 hashCode 方法ordersList.stream().filter((order) -> order.getIsValid() == 0) ? ?.distinct() ? ?.forEach(System.out::println);映射
過(guò)濾有效訂單,獲取所有訂單編號(hào)
//過(guò)濾有效訂單,獲取所有訂單編號(hào)ordersList.stream().filter((order) -> order.getIsValid() == 1) ? ?.map((order) -> order.getOrderNo()) ? ?.forEach(System.out::println);
過(guò)濾有效訂單 ,并分離每個(gè)訂單下收貨地址市區(qū)信息
ordersList.stream().map(o -> o.getAddress() ? ?.split("-")) ? ?.flatMap(Arrays::stream) ? ?.forEach(System.out::println);排序
過(guò)濾有效訂單 根據(jù)用戶id 進(jìn)行排序
//過(guò)濾有效訂單 根據(jù)用戶id 進(jìn)行排序ordersList.stream().filter((order) -> order.getIsValid() == 1) ? ?.sorted((o1, o2) -> o1.getUserId() - o2.getUserId()) ? ?.forEach(System.out::println); ? //或者等價(jià)寫(xiě)法 ordersList.stream().filter((order) -> order.getIsValid() == 1) ? ?.sorted(Comparator.comparingInt(Order::getUserId)) ? ?.forEach(System.out::println);
過(guò)濾有效訂單 ,根據(jù)訂單狀態(tài)排序 如果訂單狀態(tài)相同根據(jù)訂單創(chuàng)建時(shí)間排序
//過(guò)濾有效訂單 ?如果訂單狀態(tài)相同 根據(jù)訂單創(chuàng)建時(shí)間排序 反之根據(jù)訂單狀態(tài)排序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);// 等價(jià)形式ordersList.stream().filter((order) -> order.getIsValid() == 1) ? ?.sorted(Comparator.comparing(Order::getCreateDate) ? ?.thenComparing(Comparator.comparing(Order::getStatus))) ? ?.forEach(System.out::println);流的終止操作
終止操作會(huì)從流的流水線生成結(jié)果叫潦。其結(jié)果是任何不是流的值蝇完,比如常見(jiàn)的List、 Integer,甚 至void等結(jié)果短蜕。對(duì)于流的終止操作泛源,分為以下三類:
查找與匹配
篩選有效訂單 匹配是否全部為已支付訂單
// 篩選有效訂單 匹配是否全部為已支付訂單System.out.println("allMatch匹配結(jié)果:" + ? ? ? ? ? ? ? ? ? ? ordersList.stream() ? ? ? ? ? ? ? ? ? ? ? ?.filter((order) -> order.getIsValid() == 1) ? ? ? ? ? ? ? ? ? ? ? ?.allMatch((o) -> o.getStatus() != 0) ? ? ? ? ? ? ? ? ?);
篩選有效訂單 匹配是否存在未支付訂單
// 篩選有效訂單 匹配是否存在未支付訂單System.out.println("anyMatch匹配結(jié)果:" + ? ? ? ? ? ? ? ? ? ? ordersList.stream() ? ? ? ? ? ? ? ? ? ? ? ?.filter((order) -> order.getIsValid() == 1) ? ? ? ? ? ? ? ? ? ? ? ?.anyMatch((o) -> o.getStatus() == 0) ? ? ? ? ? ? ? ? ?);
篩選有效訂單 全部未完成訂單
// 篩選有效訂單 全部未完成訂單System.out.println("noneMatch匹配結(jié)果:" + ? ? ? ? ? ? ? ? ? ?ordersList.stream() ? ? ? ? ? ? ? ? ? ? ? ?.filter((order) -> order.getIsValid() == 1) ? ? ? ? ? ? ? ? ? ? ? ?.noneMatch((o) -> o.getStatus() == 5) ? ? ? ? ? ? ? ? ?);
篩選有效訂單 返回第一條訂單
// 篩選有效訂單 返回第一條訂單 ? ? ? ?System.out.println("findAny匹配結(jié)果:"+ ? ? ? ? ? ? ? ? ? ? ? ? ? ?ordersList.stream()?.filter((order) -> order.getIsValid() == 1) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.findAny() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .get() ? ? ? ? ? ? ? ? ? ? ? ? ?);
篩選所有有效訂單 返回訂單總數(shù)
// ?篩選所有有效訂單 返回訂單總數(shù) ? ? ? ?System.out.println("count結(jié)果:" + ? ? ? ? ? ? ? ? ? ? ? ? ? ?ordersList.stream() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.filter((order) -> order.getIsValid() == 1) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.count() ? ? ? ? ? ? ? ? ? ? ? ?);
篩選有效訂單 返回金額最大訂單金額
// 篩選有效訂單 返回金額最大訂單金額 ? ? ? ?System.out.println("訂單金額最大值:" + ? ? ? ? ? ? ? ? ? ? ? ? ? ?ordersList.stream() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.filter((order) -> order.getIsValid() == 1) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.map(Order::getTotal) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.max(Double::compare) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.get() ? ? ? ? ? ? ? ? ? ? ? ? ?);
篩選有效訂單 返回金額最小訂單金額
// 篩選有效訂單 返回金額最小訂單金額 ? ? ? ?System.out.println("訂單金額最小值:" + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ordersList.stream() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.filter((order) -> order.getIsValid() == 1) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.map(Order::getTotal) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.min(Double::compare) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.get() ? ? ? ? ? ? ? ? ? ? ? ? ?);歸約&收集1 歸約
將流中元素反復(fù)結(jié)合起來(lái),得到一個(gè)值的操作
計(jì)算有效訂單總金額
// 計(jì)算有效訂單總金額 ? ? ? ?System.out.println("有效訂單總金額:" + ? ? ? ? ? ? ? ? ? ? ? ? ? ?ordersList.stream() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.filter((order) -> order.getIsValid() == 1) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.map(Order::getTotal) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.reduce(Double::sum) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.get() ? ? ? ? ? ? ? ? ? ? ? ? ?);2 Collector數(shù)據(jù)收集
將流轉(zhuǎn)換為其他形式忿危,coollect 方法作為終端操作达箍, 接收一個(gè)Collector接口的實(shí)現(xiàn),用于給Stream中元素做匯總的方法铺厨。最常用的方法缎玫,把流中所有元素收集到一個(gè) List, Set 或 Collection中。
3 集合收集
常用集合收集方法 toList解滓、toSet赃磨、toCollection、toMap等
篩選所有有效訂單 并收集訂單列表
// 篩選所有有效訂單并收集訂單列表ordersList.stream() ? ?.filter((order) -> order.getIsValid() == 1) ? ?.collect(Collectors.toList()) ? ?.forEach(System.out::println);
篩選所有有效訂單并收集訂單號(hào)與訂單金額
// 篩選所有有效訂單 并收集訂單號(hào) 與 訂單金額Map<String,Double> map=ordersList.stream().filter((order) -> order.getIsValid() == 1). ? ?collect(Collectors.toMap(Order::getOrderNo, Order::getTotal));// java8 下對(duì)map進(jìn)行遍歷操作 如果 Map的Key重復(fù),會(huì)報(bào)錯(cuò)map.forEach((k,v)->{ ? ?System.out.println("k:"+k+":v:"+v); });匯總
匯總操作在Stream流操作比較常見(jiàn)洼裤,比如計(jì)算總數(shù)邻辉,求平均等操作,常用方法如下:
相關(guān)操作如下
篩選所有有效訂單 返回訂單總數(shù)
System.out.println("count結(jié)果:"+ ? ? ? ? ? ? ? ? ? ? ? ?ordersList.stream() ? ? ? ? ? ? ? ? ? ? ? ? ? ?.filter((order) -> order.getIsValid() == 1) ? ? ? ? ? ? ? ? ? ? ? ? ? ?.collect(Collectors.counting()) ? ? ? ? ? ? ? ? ?); System.out.println("count結(jié)果:"+ ? ? ? ? ? ? ? ? ? ? ? ?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 有效訂單平均每筆消費(fèi)金額
System.out.println("用戶id=20 有效訂單平均每筆消費(fèi)金額:"+ ? ? ? ? ? ? ? ? ? ? ? ?ordersList.stream() ? ? ? ? ? ? ? ? ? ? ? ? ? ?.filter((order) -> order.getIsValid() == 1) ? ? ? ? ? ? ? ? ? ? ? ? ? ?.filter((order -> order.getUserId()==20)) ? ? ? ? ? ? ? ? ? ? ? ? ? ?.collect(Collectors.averagingDouble(Order::getTotal)) ? ? ? ? ? ? ? ? ?); System.out.println("用戶id=20 有效訂單平均每筆消費(fèi)金額:"+ ? ? ? ? ? ? ? ? ? ? ? ?ordersList.stream() ? ? ? ? ? ? ? ? ? ? ? ? ? ?.filter((order) -> order.getIsValid() == 1) ? ? ? ? ? ? ? ? ? ? ? ? ? ?.filter((order -> order.getUserId()==20)) ? ? ? ? ? ? ? ? ? ? ? ? ? ?.mapToDouble(Order::getTotal) ? ? ? ? ? ? ? ? ? ? ? ? ? ?.average() ? ? ? ? ? ? ? ? ? ? ? ? ? ?.getAsDouble() ? ? ? ? ? ? ? ? ?); System.out.println("用戶id=20 有效訂單平均每筆消費(fèi)金額:"+ ? ? ? ? ? ? ? ? ? ? ? ?ordersList.stream() ? ? ? ? ? ? ? ? ? ? ? ? ? ?.filter((order) -> order.getIsValid() == 1) ? ? ? ? ? ? ? ? ? ? ? ? ? ?.filter((order -> order.getUserId()==20)) ? ? ? ? ? ? ? ? ? ? ? ? ? ?.collect(Collectors.summarizingDouble(Order::getTotal)) ? ? ? ? ? ? ? ? ? ? ? ? ? ?.getAverage() ? ? ? ? ? ? ? ? ?);
篩選所有有效訂單 并計(jì)算訂單總金額
System.out.println("訂單總金額:"+ ? ? ? ? ? ? ? ? ? ? ? ?ordersList.stream() ? ? ? ? ? ? ? ? ? ? ? ? ? ?.filter((order) -> order.getIsValid() == 1) ? ? ? ? ? ? ? ? ? ? ? ? ? ?.collect(Collectors.summingDouble(Order::getTotal)) ? ? ? ? ? ? ? ? ?);最值
篩選所有有效訂單 并計(jì)算最小訂單金額
System.out.println("最小訂單金額:"+ ? ? ? ? ? ? ? ? ? ? ? ?ordersList.stream() ? ? ? ? ? ? ? ? ? ? ? ? ? ?.filter((order) -> order.getIsValid() == 1) ? ? ? ? ? ? ? ? ? ? ? ? ? ?.map(Order::getTotal) ? ? ? ? ? ? ? ? ? ? ? ? ? ?.collect(Collectors.minBy(Double::compare)) ? ? ? ? ? ? ? ? ?);
篩選所有有效訂單 并計(jì)算最大訂單金額
// 篩選所有有效訂單 并計(jì)算最大訂單金額System.out.println("最大訂單金額:"+ ? ? ? ? ? ? ? ? ? ? ? ?ordersList.stream() ? ? ? ? ? ? ? ? ? ? ? ? ? ?.filter((order) -> order.getIsValid() == 1) ? ? ? ? ? ? ? ? ? ? ? ? ? ?.map(Order::getTotal) ? ? ? ? ? ? ? ? ? ? ? ? ? ?.collect(Collectors.maxBy(Double::compare)) ? ? ? ? ? ? ? ? ?);分組&分區(qū)1 分組
groupingBy 用于將數(shù)據(jù)分組腮鞍,最終返回一個(gè) Map 類型 值骇,groupingBy 第二參數(shù)用于實(shí)現(xiàn)多級(jí)分組
根據(jù)有效訂單支付狀態(tài)進(jìn)行分組操作
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("訂單狀態(tài):"+status); ? ?order.forEach(System.out::println); });
篩選有效訂單,根據(jù)用戶id 和 支付狀態(tài)進(jìn)行分組
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 "待發(fā)貨"; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}else if (o.getStatus()==3){ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?return "已發(fā)貨"; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}else if (o.getStatus()==4){ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?return "已接收"; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?} else{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?return "已完成"; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?)) ? ? ? ? ? ? ? ? ? ? ? ? ? ?); g02.forEach((userId,m)->{ ? ?System.out.println("用戶id:"+userId+"-->有效訂單如下:"); ? ?m.forEach((status,os)->{ ? ? ? ?System.out.println("狀態(tài):"+status+"---訂單列表如下:"); ? ? ? ?os.forEach(System.out::println); ? ?}); ? ?System.out.println("-----------------------"); });2 分區(qū)
分區(qū)與分組的區(qū)別在于移国,分區(qū)是按照 true 和 false 來(lái)分的吱瘩,因此partitioningBy 接受的參數(shù)的 lambda 也是?T -> boolean
分區(qū)操作-篩選訂單金額>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("分區(qū)結(jié)果:"+b+"--列表結(jié)果:"); ? ?os.forEach(System.out::println); });
拼接操作-篩選有效訂單并進(jìn)行拼接
String orderStr=ordersList.stream() ? ? ? ? ? ?.filter((order) -> order.getIsValid() == 1) ? ? ? ? ? ?.map(Order::getOrderNo) ? ? ? ? ? ?.collect(Collectors.joining(",")); System.out.println(orderStr);流的應(yīng)用
Java8引入Stream流操作,使得對(duì)元素的處理更加的方便快捷迹缀,通過(guò)Stream提供的相關(guān)方法很好的結(jié)合Lambda使碾、函數(shù)式接口、方法引用等相關(guān)內(nèi)容祝懂,使得流的處理相比較原始集合處理代碼極大簡(jiǎn)化票摇,Stream支持函數(shù)的鏈?zhǔn)秸{(diào)用,代碼上更加緊湊同時(shí)Stream支持的元素的并行化處理提高了程序的執(zhí)行性能砚蓬。
對(duì)于Stream流的應(yīng)用通常在集合元素?cái)?shù)據(jù)處理上特別是對(duì)元素需要進(jìn)行多次處理的情況矢门,同時(shí)對(duì)于函數(shù)式編程的味道更加濃重,也是以后開(kāi)發(fā)的一個(gè)趨勢(shì)怜械。