java8 新特性入門 stream/lambda

Java 8 中的 Stream 是對集合(Collection)對象功能的加強,它專一於對集合對象進行各類很是便利、高效的聚合操做(aggregate operation),或者大批量數據操做 (bulk data operation)。Stream API 藉助於一樣新出現的 Lambda 表達式,極大的提升編程效率和程序可讀性。同時它提供串行和並行兩種模式進行匯聚操做,併發模式可以充分利用多核處理器的優點java

Stream 不是集合元素,它不是數據結構並不保存數據,它是有關算法和計算的,它更像一個高級版本的 Iterator。獲取一個數據源(source)→ 數據轉換→執行操做獲取想要的結果,每次轉換原有 Stream 對象不改變,返回一個新的 Stream 對象(能夠有屢次轉換),這就容許對其操做能夠像鏈條同樣排列,變成一個管道算法

爲何不在集合類實現這些操做,而是定義了全新的Stream API?Oracle官方給出了幾個重要緣由:express

一是集合類持有的全部元素都是存儲在內存中的,很是巨大的集合類會佔用大量的內存,而Stream的元素倒是在訪問的時候才被計算出來,這種「延遲計算」的特性有點相似Clojure的lazy-seq,佔用內存不多。編程

二是集合類的迭代邏輯是調用者負責,一般是for循環,而Stream的迭代是隱含在對Stream的各類操做中,例如map()數組

對於基本數值型,目前有三種對應的包裝類型 Stream:IntStream、LongStream、DoubleStream。數據結構

 

  stream是Java8新增的一大API。官方定義:支持在元素流上支持功能式操做,例如映射減小集合上的轉換。多線程

特色:併發

       不儲存。數據流不是存儲元素的數據結構;相反,它將元素從源數據結構、數組、生成器函數或輸入/輸出通道傳遞到計算操做的管道中。dom

       功能性。一個流操做產生一個結果,但不修改它的源。例如,從一個集合中過濾獲得的數據流產生一個新的流,而不過濾元素,而不是從源集合中移除元素。函數

        懶惰尋求。許多流操做,如過濾、映射,或去除重複,能夠懶洋洋地,暴露的機會,優化。例如,「尋找三個連續的元音字母的第一個字符串」不須要檢查全部的輸入字符串。流操做分爲中間(流生產)操做和終端(價值或反作用生產)操做。中間操做老是懶惰。

       可能無界。雖然集合有一個有限的大小,流不須要。短路操做如極限(n)或findfirst()能夠容許無限流計算在有限的時間內完成.

        意爲流但與I/O流又有所不一樣。Stream 是對集合(Collection)對象功能的加強,它專一於對集合對象進行各類很是便利、高效的聚合操做(aggregate operation),或者大批量數據操做 (bulk data operation)。Stream API 藉助於一樣新出現的 Lambda 表達式,極大的提升編程效率和程序可讀性。同時它提供串行和並行兩種模式進行匯聚操做,併發模式可以充分利用多核處理器的優點,使用 fork/join 並行方式來拆分任務和加速處理過程。一般編寫並行代碼很難並且容易出錯, 但使用 Stream API 無需編寫一行多線程的代碼,就能夠很方便地寫出高性能的併發程序。因此說,Java 8 中首次出現的 java.util.stream 是一個函數式語言+多核時代綜合影響的產物。

Lambda語法:

(params) -> expression
(params) -> statement
(params) -> { statements }

 

關鍵字:

filter:是一箇中間操做,接受一個predicate接口類型的變量,並將全部流對象中的元素進行過濾。filter(s -> s.getState()==State.pay)

map:是一個對於流對象的中間操做,經過給定的方法,它可以把流對象中的每個元素對應到另一個對象上。map(s -> s.getPlanNo()) / map(s -> Plan::planNo)  /  價格變成    10倍 map(s -> s.getPrice().multiply(BigDecimal.valueOf(10)))

reduce:把 Stream 元素組合起來。它提供一個起始值(種子),而後依照運算規則(BinaryOperator),返回單個的結果值,而且reduce操做每處理一個元素老是建立一個新值

          BigDecimal total = stream().reduce(BigDecimal.zero, (a,b) -> a.add(b));   或

          BigDecimal total = stream().reduce(BigDecimal.ZERO, BigDecimal::add)

limit : 返回 Stream 的前面 n 個元素;skip 則是扔掉前 n 個元素

sorted: 一箇中間操做,可以返回一個排過序的流對象的視圖。流對象中的元素會默認按照天然順序進行排序,除非你本身指定一個Comparator接口來改變排序規則.

 

collect: 修改現存的值

Collectors 類的主要做用就是輔助進行各種有用的 reduction 操做

groupingBy  按規則分組:stream().collect(Collectors.groupingBy(p->p.getState()))

partitioningBy 是一種特殊的 groupingBy,它依照條件測試的是否兩種結果來構造返回的數據結構,get(true) 和 get(false) 能即爲所有的元素對象。

 

Stream 有三個 match 方法,從語義上說:

allMatch:Stream 中所有元素符合傳入的 predicate,返回 true

anyMatch:Stream 中只要有一個元素符合傳入的 predicate,返回 true

noneMatch:Stream 中沒有一個元素符合傳入的 predicate,返回 true

 

示例,domain

public class Plan {
    private int id;    
    private String planNo;    
    private BigDecimal price;    
    private long total;    
    private State state;    
    private Calendar createTime;    
    private JSONObject features = new JSONObject();

Sate :noPay(1,"未支付"),     pay(2,"支付"),      settle(3,"結算"),

 

List<Plan>  planList = initList();

1. 把方案編號planNo轉換大寫 返回列表

List<String> noList = planList.stream().map(p->p.getPlanNo().toUpperCase()).collect(Collectors.toList());

 

2,價格由高到低排序

List<Plan> list = planList.stream().sorted((a,b) -> b.getPrice().compareTo(a.getPrice())).collect(Collectors.toList());

 

3,狀態爲支付的價格由高到低排序

planList.stream().filter(s -> State.pay == s.getState()).sorted((a,b) -> b.getPrice().compareTo(a.getPrice())).collect(Collectors.toList());

4,求最高價/最低價/總價,   total數量平均,總和

BigDecimal max = planList.stream().max((a,b)->a.getPrice().compareTo(b.getPrice())).get().getPrice();
BigDecimal min = planList.stream().min((a,b)->a.getPrice().compareTo(b.getPrice())).get().getPrice();
BigDecimal total = planList.stream().map(p->p.getPrice()).reduce(BigDecimal.ZERO,(a,b)->a.add(b));

平均 : planList.stream().mapToLong(Plan::getTotal).average().getAsDouble();

總和:planList.stream().mapToLong(Plan::getTotal).sum()

5,總共有多少種狀態值

long count = planList.stream().map(p->p.getState()).distinct().count();
long c2 = planList.stream().map(p->p.getState()).collect(Collectors.toSet()).size();

 

6,方案編號中包含某些字符

List<Plan> list = planList.stream().filter(p->p.getPlanNo().contains("gt")).collect(Collectors.toList());

 

7,價格前三的方案

List<Plan> topList = planList.stream().sorted((a,b)->b.getPrice().compareTo(a.getPrice())).limit(3).collect(Collectors.toList());

 

8,按方案狀態分組列表

Map<State, List<Plan>> map = planList.stream().collect(Collectors.groupingBy(p->p.getState()));

 

9,方案分紅是否支付二種,查詢列表

Map<Boolean, List<Plan>> map = planList.stream().collect(Collectors.partitioningBy(s -> s.getState()==State.noPay));

map.get(true) 是所有 未支付

map.get(false) 是支付 和 結算

 

10,轉換成Map結構 <方案編號 ,  價格>

Map<String, BigDecimal> map = planList.stream().collect(Collectors.toMap(p->p.getPlanNo(), Plan::getPrice));

 

11,轉換數據結構 ,  list轉成數組  

Plan[] ps = planList.stream().toArray(Plan[]::new);

 

12,按狀態算數量的總和/平均數

平均:Map<State, Double> map = planList.stream().collect(Collectors.groupingBy(Plan::getState, Collectors.averagingLong(Plan::getTotal)));

求和:Map<State, Long> sum = planList.stream().collect(Collectors.groupingBy(Plan::getState, Collectors.summingLong(Plan::getTotal)));

 

Map<State, LongSummaryStatistics> sumMap =  planList.stream().collect(Collectors.groupingBy(Plan::getState, Collectors.summarizingLong(Plan::getTotal)));

LongSummaryStatistics描述流中元素的各類摘要數據,求 count, min, max, sum, and average.

相關文章
相關標籤/搜索