十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
這篇文章主要為大家展示了“Java8中stream和functional interface怎么用”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Java8中stream和functional interface怎么用”這篇文章吧。
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡(jiǎn)單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名注冊(cè)、網(wǎng)站空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、道里網(wǎng)站維護(hù)、網(wǎng)站推廣。
generate 與 Supplier
stream 最常見的來源是 Collection。Collection 是一組可遍歷元素的抽象容器。它有兩大類實(shí)現(xiàn):不允許重復(fù)元素的 Set 和允許重復(fù)的 List。只要在某個(gè) Collection 對(duì)象后面加上 .stream() 或者 .parallelStream() 就可以得到相應(yīng)的 stream 了。
如果沒有現(xiàn)成的 Collection,或者 Collection 太大根本存不下,還有什么辦法可以生成 stream 么?如果知道生成 stream 中每個(gè)元素的算法,就可以無中生有造出一個(gè) stream 來。這里用到的是方法 Stream.generate(),它依賴于一個(gè)函數(shù)式接口 Supplier。
staticStream generate(Supplier s);
Supplier 的方法 get() 在每次調(diào)用時(shí)都返回一個(gè) T 的對(duì)象。因?yàn)?get() 方法不接收任何參數(shù),所以使用 generate 時(shí),代碼總是會(huì)寫成類似 () -> returnValue 的樣子。
另外,由于 get() 可以被調(diào)用無限多次,因此通過 generate 生成的 stream 也是無限長(zhǎng)的,必要時(shí)可以通過 .limit() 截取前若干個(gè)元素。
例如,如果想獲得一個(gè)無限長(zhǎng)的隨機(jī) UUID 序列,可以使用下面的方法:
StreaminfiniteUUIDStream = Stream.generate(() -> UUID.randomUUID());
想要獲取諸如 1 ~ 10 這樣的序列也是可行的,但需要一個(gè) helper class 記錄當(dāng)前狀態(tài),這里就不提供案例了。
forEach 與 Consumer
知道了如何生成 stream,也要知道如何消費(fèi)它。既然 stream 可以從 Collection 來,那么最后應(yīng)該也能變成 Collection,這就是 collect() 的功勞了。collect() 接收一個(gè) Collector 作為參數(shù),返回從 stream 生成的 Collection 對(duì)象。不過這個(gè) Collector 不是函數(shù)式接口,所以不屬于本文的重點(diǎn)。下面著重講解的是 forEach 方法。
void forEach(Consumer super T> action);
forEach 與函數(shù)式接口 Consumer 配合工作,Consumer 的 void accept(T t) 方法就是來消費(fèi) stream 中的各個(gè)元素的。因?yàn)?accept 接收單個(gè)元素 T 作為參數(shù),forEach 會(huì)寫成 e -> statement 的形式,其中 statement 不返回任何值。
比如,逐行打印 stream 中的每一個(gè)元素,就可以寫作:
stream.forEach(e -> System.out.println(e));
或者通過方法引用進(jìn)一步簡(jiǎn)化:
stream.forEach(System.out::println);
reduce 與 BinaryOperator
除了 forEach 這種吞噬元素的終結(jié)型操作以外,使用 stream 中的元素還有兩種常見的模式。第一種依舊是終結(jié)型操作:整合所有的元素,最后返回一個(gè)單一的值,我們把這個(gè)操作稱作 reduce。第二種則是過程性操作,它讓每個(gè)元素都有自己對(duì)應(yīng)的返回值,之后重組成為新的 stream,以便下一步繼續(xù)利用。我們把第二種操作稱為 map。把剛剛提及的這兩個(gè)操作結(jié)合起來,就是大名鼎鼎的 MapReduce 了(誤)。
reduce 與一種特殊的函數(shù)式接口搭配使用,它叫 BinaryOperator。BinaryOperator
講解 reduce 時(shí)最常見的例子就是求一個(gè) stream 中所有元素之和了:
// stream: StreamOptional sum = stream.reduce((a, b) -> a + b);
我們可以看出,reduce 方法的特征是 (a, b) -> returnValue。它返回的結(jié)果是 Optional,我們可以用 .isPresent() 查看是否為空值;當(dāng)值不為空時(shí),用 .get() 獲取數(shù)據(jù)。
map 與 Function
map 或許是 stream 中使用最為廣泛的一個(gè)操作了。與 reduce 涉及的 BiFunction 不同,與 map 配套使用的函數(shù)式接口是略為簡(jiǎn)單的 Function。它同樣是一個(gè)寬泛的函數(shù)式接口,同時(shí)也是函數(shù)式接口最著名的代表。Function
比如說,把一個(gè) stream 中的每一個(gè)字符串都變成大寫:
// original: StreamStream transformed = original.map(e -> e.toUpperCase());
map 方法的特征是 e -> returnValue。正如我們之前用過的 System.out::println 一樣,這里也可以使用方法引用簡(jiǎn)化代碼,只要引用的方法符合 map 預(yù)期的類型即可:傳入一個(gè) T 參數(shù),返回一個(gè) R 值。
// original: StreamStream transformed = original.map(String::toUpperCase);
filter 與 Predicate
介紹了 forEach,reduce 和 map 這些重量級(jí)的操作,下面我們來處理一個(gè)尷尬的問題:如果這個(gè) stream 中有我們不想要的元素怎么辦?答案是使用 filter 把他們踢出去。
與 filter 搭配使用的函數(shù)式接口是 Predicate。Predicate
在下面的例子中,程序只打印 stream 中的偶數(shù):
// stream: Streamstream.filter(e -> e % 2 == 0).forEach(System.out::println);
可以看出,由于 Predicate 是一種特異的 Function,所以 filter 方法的特征與 map 在外觀上如出一轍。不過 filter 要保證 e -> returnValue 中的 returnValue 是一個(gè) boolean,否則編譯會(huì)報(bào)錯(cuò)。
sorted 與 Comparator
最后來看看 stream 中非常強(qiáng)大的 sorted 方法,它允許我們自定義比較規(guī)則對(duì) stream 中的元素排序。與 sorted 搭配的函數(shù)式接口是 Comparator,Comparator
接下來的例子將 stream 中的浮點(diǎn)數(shù)按絕對(duì)值的升序排列,并打印出來:
// stream: Streamstream.sorted((a, b) -> { double diff = a - b; if (diff < 0) return -1; else if (diff > 0) return 1; else return 0; }).forEach(System.out::println);
不難看出,sorted 方法的特征與 reduce 比較相似,都是 (a, b) -> returnValue 的結(jié)構(gòu),但是要保證 returnValue 是 int 類型。
以上是“Java8中stream和functional interface怎么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!