java stream流_Java-8-流(1)
Java-8-流(1)
外部迭代與內部迭代
Java 程序員在使用集合類時,一個通用的模式是在集合上進行迭代,然后處理返回的每一 個元素
在數字集合里面統計大于100的數有幾個
public盡管這樣的操作可行,但存在幾個問題。每次迭代集合類時,都需要寫很多樣板代碼。將for 循環改造成并行方式運行也很麻煩,需要修改每個 for 循環才能實現
for 循環的樣板代碼模糊了代碼的本意,程序員必須閱讀整個循環體才能理解。若是單一的 for 循環,倒也問題不大,但面對一個滿是循環(尤其是嵌套循環)的龐大代碼庫時,負擔就重了
for 循環其實是一個封裝了迭代的語法糖看看它的工作原理。首先調用 iterator 方法,產生一個新的 Iterator 對象,進而控制整個迭代過程,這就是外部迭代。迭代過程通過顯式調用 Iterator 對象的 hasNext 和 next方法完成迭代
使用迭代器在數字集合里面統計大于100的數有幾個
int簡單理解外部迭代就是由用戶來決定”做什么“和”怎么做“的操作
另一種方法就是內部迭代
使用內部迭在數字集合里面統計大于100的數有幾個
List每種操作都對應 Stream 接口的一個方法。為了找出來大于100的數有幾個,需要對 Stream 對象進行過濾: filter 。過濾在這里是指“只保留通過某項測試的對象”。測試由一個函數完成,根據數字是否大于100,該函數返回 true 或者 false 。由于 Stream API 的函數式編程風格,我們并沒有改變集合的內容,而是描述出 Stream 里的內容。 count() 方法計算給定 Stream 里包含多少個對象
內部迭代我們只需要提供”做什么“,把”怎么做“的任務交給了 JVM
使用內部迭代可以帶來的好處:
- 用戶只需要關注問題,無需關注如何解決問題的細節
- 使得 JVM可以利用短路、并行等對性能的提升變成可能
Stream
Stream(流)是一個來自數據源的元素隊列并支持聚合操作
- 元素是特定類型的對象,形成一個隊列。 Java中的Stream并不會存儲元素,而是按需計算。
- 數據源 流的來源。 可以是集合,數組,I/O channel, 產生器generator 等。
- 聚合操作 類似SQL語句一樣的操作, 比如filter, map, reduce, find, match, sorted等。
以前的Collection操作不同, Stream操作還有兩個基礎的特征:
- Pipelining: 中間操作都會返回流對象本身。 這樣多個操作可以串聯成一個管道, 如同流式風格(fluent style)。 這樣做可以對操作進行優化, 比如延遲執行(laziness)和短路( short-circuiting)。
- 內部迭代: 以前對集合遍歷都是通過Iterator或者For-Each的方式, 顯式的在集合外部進行迭代, 這叫做外部迭代。 Stream提供了內部迭代的方式, 通過訪問者模式(Visitor)實現。
在 Java 8 中, 集合接口有兩個方法來生成流:
- stream() ? 為集合創建串行流。
- parallelStream() ? 為集合創建并行流。
流的操作類型
- Intermediate:一個流可以后面跟隨零個或多個 intermediate 操作。其目的主要是打開流,做出某種程度的數據映射/過濾,然后返回一個新的流,交給下一個操作使用。這類操作都是惰性化的(lazy),就是說,僅僅調用到這類方法,并沒有真正開始流的遍歷
- Terminal:一個流只能有一個 terminal 操作,當這個操作執行后,流就被使用“光”了,無法再被操作。所以這必定是流的最后一個操作。Terminal 操作的執行,才會真正開始流的遍歷,并且會生成一個結果,或者一個 side effect。
在對于一個 Stream 進行多次轉換操作 (Intermediate 操作),每次都對 Stream 的每個元素進行轉換,而且是執行多次,這樣時間復雜度就是 N(轉換次數)個 for 循環里把所有操作都做掉的總和嗎?
其實不是這樣的,轉換操作都是 lazy 的,多個轉換操作只會在 Terminal 操作的時候融合起來,一次循環完成。我們可以這樣簡單的理解,Stream 里有個操作函數的集合,每次轉換操作就是把轉換函數放入這個集合中,在 Terminal 操作的時候循環 Stream 對應的集合,然后對每個元素執行所有的函數。
流的構造與轉換
public自己構造流
Stream.generate
Stream.generate通過實現 Supplier 接口,你可以自己來控制流的生成
publicStream.generate() 還接受自己實現的 Supplier。例如在構造海量測試數據的時候,用某種自動的規則給每一個變量賦值
publicStream.iterate
public流可以轉換為數組、集合
public常用的流操作
collect
Collectors.toList():轉換成List集合
publicCollectors.toCollection(TreeSet::new):轉換成特定的set集合
publicCollectors.toMap(keyMapper, valueMapper, mergeFunction):轉換成map
publicCollectors.minBy(Integer::compare):求最小值
publicCollectors.averagingInt(x->x):求平均值
publicCollectors.summingInt(x -> x)):求和
publicCollectors.summarizingDouble(x -> x):可以獲取最大值、最小值、平均值、總和值、總數
publiccounting:Stream的元素個數
public分組groupingBy
groupingBy()是Stream API中最強大的收集器Collector之一,提供與SQL的GROUP BY子句類似的功能。
使用形式如下:
.按長度對字符串進行分組
public如果需要提供自定義Map實現,可以使用提供的groupingBy()重載來實現
public分組計數
publicUser類
public多個屬性拼接出一個組合屬性
public分組和計算每組的總和
派生每組條目的平均屬性,那么有一些方便的收集器:
- averagingInt()
- averagingLong()
- averagingDouble()
分組和計算每組的總和
對分組條目進行累計總和:
- summingInt()
- summingLong()
- summingDouble()
計算最大最小值
public輸出:
{Collectors.partitioningBy(x -> x > 2)
在JDK8中,可以對流進行方便的自定義分塊,通常是根據某種過濾條件將流一分為二
partitioningBy函數的定義如下:
public函數的參數一個Predicate接口,那么這個接口的返回值是boolean類型的,也只能是boolean類型,然后他的返回值是Map的key是boolean類型,也就是這個函數的返回值只能將數據分為兩組也就是ture和false兩組數據
例子:
public把隨機數字根據是否大于150分成兩組
publicCollectors.joining(","):拼接字符串
在JDK8中,可以采用函數式編程(使用 Collectors.joining 收集器)的方式對字符串進行更優雅的連接。Collectors.joining 收集器 支持靈活的參數配置,可以指定字符串連接時的 分隔符,前綴 和 后綴 字符串
publicCollectors.mapping(...)
可以把收集到的數據傳遞給 Collectors.mapping() 方法進行映射處理,以獲取一些特定的信息mapping() 方法接收兩個參數,第一個參數為如何處理每一條數據,第二個參數為當 mapping 完成后如何處理數據
例子:
public總結
以上是生活随笔為你收集整理的java stream流_Java-8-流(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑安装系统难不难电脑装机难不难
- 下一篇: java 字符串赋值_灵魂拷问:为什么