最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java8中stream和functional interface的配合使用詳解

 更新時間:2017年11月14日 11:10:50   作者:Ming  
這篇文章主要給大家介紹了關(guān)于Java8中stream和functional interface配合使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用java8具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。

前言

Java 8 提供了一組稱為 stream 的 API,用于處理可遍歷的流式數(shù)據(jù)。stream API 的設(shè)計,充分融合了函數(shù)式編程的理念,極大簡化了代碼量。

大家其實可以把Stream當(dāng)成一個高級版本的Iterator。原始版本的Iterator,用戶只能一個一個的遍歷元素并對其執(zhí)行某些操作;高級版本的Stream,用戶只要給出需要對其包含的元素執(zhí)行什么操作,比如“過濾掉長度大于10的字符串”、“獲取每個字符串的首字母”等,具體這些操作如何應(yīng)用到每個元素上,就給Stream就好了?。ㄟ@個秘籍,一般人我不告訴他:))

我們來講解如何將常用的 stream API 與相應(yīng)的 functional interface (函數(shù)式接口)配合使用,達(dá)成數(shù)據(jù)處理的目的。

類似于困擾哲學(xué)家們數(shù)千年的三大問題,關(guān)于 stream 我們也有三個疑團(tuán)需要解開:它從哪里來?它能做什么?它會變成什么?

generate 與 Supplier

stream 最常見的來源是 Collection。Collection 是一組可遍歷元素的抽象容器。它有兩大類實現(xiàn):不允許重復(fù)元素的 Set 和允許重復(fù)的 List。只要在某個 Collection 對象后面加上 .stream() 或者 .parallelStream() 就可以得到相應(yīng)的 stream 了。

如果沒有現(xiàn)成的 Collection,或者 Collection 太大根本存不下,還有什么辦法可以生成 stream 么?如果知道生成 stream 中每個元素的算法,就可以無中生有造出一個 stream 來。這里用到的是方法 Stream.generate(),它依賴于一個函數(shù)式接口 Supplier。

static <T> Stream<T> generate(Supplier<T> s);

Supplier 的方法 get() 在每次調(diào)用時都返回一個 T 的對象。因為 get() 方法不接收任何參數(shù),所以使用 generate 時,代碼總是會寫成類似 () -> returnValue 的樣子。

另外,由于 get() 可以被調(diào)用無限多次,因此通過 generate 生成的 stream 也是無限長的,必要時可以通過 .limit() 截取前若干個元素。

例如,如果想獲得一個無限長的隨機(jī) UUID 序列,可以使用下面的方法:

Stream<UUID> infiniteUUIDStream = Stream.generate(() -> UUID.randomUUID());

想要獲取諸如 1 ~ 10 這樣的序列也是可行的,但需要一個 helper class 記錄當(dāng)前狀態(tài),這里就不提供案例了。

forEach 與 Consumer

知道了如何生成 stream,也要知道如何消費它。既然 stream 可以從 Collection 來,那么最后應(yīng)該也能變成 Collection,這就是 collect() 的功勞了。collect() 接收一個 Collector 作為參數(shù),返回從 stream 生成的 Collection 對象。不過這個 Collector 不是函數(shù)式接口,所以不屬于本文的重點。下面著重講解的是 forEach 方法。

void forEach(Consumer<? super T> action);

forEach 與函數(shù)式接口 Consumer 配合工作,Consumer 的 void accept(T t) 方法就是來消費 stream 中的各個元素的。因為 accept 接收單個元素 T 作為參數(shù),forEach 會寫成 e -> statement 的形式,其中 statement 不返回任何值。

比如,逐行打印 stream 中的每一個元素,就可以寫作:

stream.forEach(e -> System.out.println(e));

或者通過方法引用進(jìn)一步簡化:

stream.forEach(System.out::println);

reduce 與 BinaryOperator

除了 forEach 這種吞噬元素的終結(jié)型操作以外,使用 stream 中的元素還有兩種常見的模式。第一種依舊是終結(jié)型操作:整合所有的元素,最后返回一個單一的值,我們把這個操作稱作 reduce。第二種則是過程性操作,它讓每個元素都有自己對應(yīng)的返回值,之后重組成為新的 stream,以便下一步繼續(xù)利用。我們把第二種操作稱為 map。把剛剛提及的這兩個操作結(jié)合起來,就是大名鼎鼎的 MapReduce 了(誤)。

reduce 與一種特殊的函數(shù)式接口搭配使用,它叫 BinaryOperator。BinaryOperator<T> 的原型是 BiFunction<T, T, T>,那這個 BiFunction 又是怎么回事呢?原來,BiFunction<T, U, R> 是一個寬泛的函數(shù)式接口,它的方法 R apply(T t, U u) 接受類型為 T 和 U 的兩個參數(shù),并返回一個類型為 R 的值。如果 T U R 這三者的類型相同,就可以寫作 BiFunction<T, T, T>。因為這種用法尤其常見,于是它有了自己專屬的名字,即 BinaryOperator<T>。最常見的 BinaryOperator 當(dāng)屬二元算術(shù)操作,我們熟知的加減乘除都屬于這個范疇。

講解 reduce 時最常見的例子就是求一個 stream 中所有元素之和了:

// stream: Stream<Integer>
Optional<Integer> sum = stream.reduce((a, b) -> a + b);

我們可以看出,reduce 方法的特征是 (a, b) -> returnValue。它返回的結(jié)果是 Optional,我們可以用 .isPresent() 查看是否為空值;當(dāng)值不為空時,用 .get() 獲取數(shù)據(jù)。

map 與 Function

map 或許是 stream 中使用最為廣泛的一個操作了。與 reduce 涉及的 BiFunction 不同,與 map 配套使用的函數(shù)式接口是略為簡單的 Function。它同樣是一個寬泛的函數(shù)式接口,同時也是函數(shù)式接口最著名的代表。Function<T, R> 的方法 R apply(T t) 接受一個類型為 T 的參數(shù),并返回一個類型為 R 的值。map 所做的事情,就是把這個 Function 應(yīng)用于 stream 中的每一個元素,以得到一個新的全部由 R 組成的 stream。

比如說,把一個 stream 中的每一個字符串都變成大寫:

// original: Stream<String>
Stream<String> transformed = original.map(e -> e.toUpperCase());

map 方法的特征是 e -> returnValue。正如我們之前用過的 System.out::println 一樣,這里也可以使用方法引用簡化代碼,只要引用的方法符合 map 預(yù)期的類型即可:傳入一個 T 參數(shù),返回一個 R 值。

// original: Stream<String>
Stream<String> transformed = original.map(String::toUpperCase);

filter 與 Predicate

介紹了 forEach,reduce 和 map 這些重量級的操作,下面我們來處理一個尷尬的問題:如果這個 stream 中有我們不想要的元素怎么辦?答案是使用 filter 把他們踢出去。

與 filter 搭配使用的函數(shù)式接口是 Predicate。Predicate<T> 的方法 boolean test(T t) 接受一個類型為 T 的參數(shù),并返回 true 或是 false。我們可以認(rèn)為 Predicate<T> 就是特異化的 Function<T, boolean>,因為它使用得足夠廣泛,所以自立門戶成為一套單獨的接口。

在下面的例子中,程序只打印 stream 中的偶數(shù):

// stream: Stream<Integer>
stream.filter(e -> e % 2 == 0).forEach(System.out::println);

可以看出,由于 Predicate 是一種特異的 Function,所以 filter 方法的特征與 map 在外觀上如出一轍。不過 filter 要保證 e -> returnValue 中的 returnValue 是一個 boolean,否則編譯會報錯。

sorted 與 Comparator

最后來看看 stream 中非常強大的 sorted 方法,它允許我們自定義比較規(guī)則對 stream 中的元素排序。與 sorted 搭配的函數(shù)式接口是 Comparator,Comparator<T> 使用 int compare(T o1, T o2) 方法比較兩個 T 類型的對象。排序正是通過比較對象之間的相對大小實現(xiàn)的。

接下來的例子將 stream 中的浮點數(shù)按絕對值的升序排列,并打印出來:

// stream: Stream<Double>
stream.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 類型。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • Java操作excel的三種常見方法實例

    Java操作excel的三種常見方法實例

    這篇文章主要給大家介紹了關(guān)于Java操作excel的三種常見方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • java學(xué)習(xí)之利用TCP實現(xiàn)的簡單聊天示例代碼

    java學(xué)習(xí)之利用TCP實現(xiàn)的簡單聊天示例代碼

    這篇文章主要給大家介紹了關(guān)于java學(xué)習(xí)筆記之利用TCP實現(xiàn)的簡單聊天的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-12-12
  • Java8 將List轉(zhuǎn)換為用逗號隔開的字符串的多種方法

    Java8 將List轉(zhuǎn)換為用逗號隔開的字符串的多種方法

    這篇文章主要介紹了Java8 將List轉(zhuǎn)換為用逗號隔開的字符串的幾種方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • Java實現(xiàn)爬取往期所有雙色球開獎結(jié)果功能示例

    Java實現(xiàn)爬取往期所有雙色球開獎結(jié)果功能示例

    這篇文章主要介紹了Java實現(xiàn)爬取往期所有雙色球開獎結(jié)果功能,涉及Java網(wǎng)頁抓取、正則替換、文件讀寫等相關(guān)操作技巧,需要的朋友可以參考下
    2018-07-07
  • 一文搞懂Spring中的JavaConfig

    一文搞懂Spring中的JavaConfig

    這篇文章主要介紹了Spring中的JavaConfig知識,包括事務(wù)注解驅(qū)動,properties配置文件加載方法,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2021-09-09
  • spring(java,js,html) 截圖上傳圖片實例詳解

    spring(java,js,html) 截圖上傳圖片實例詳解

    這篇文章主要介紹了spring(java,js,html) 截圖上傳圖片實例詳解的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-07-07
  • JavaEE7+Websockets+GlassFish4打造聊天室

    JavaEE7+Websockets+GlassFish4打造聊天室

    Java EE 7已經(jīng)發(fā)布很久了,新增加了很多新的功能和特性,如新增或更新了不少的JSR標(biāo)準(zhǔn)。其中特別受到關(guān)注的是Websockets。它的一個好處之一是減少了不必要的網(wǎng)絡(luò)流量。它主要是用于在客戶機(jī)和服務(wù)器之間建立單一的雙向連接。
    2015-09-09
  • Springmvc ResponseBody響應(yīng)json數(shù)據(jù)實現(xiàn)過程

    Springmvc ResponseBody響應(yīng)json數(shù)據(jù)實現(xiàn)過程

    這篇文章主要介紹了Springmvc ResponseBody響應(yīng)json數(shù)據(jù)實現(xiàn)過程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-10-10
  • Spring4如何自定義@Value功能詳解

    Spring4如何自定義@Value功能詳解

    這篇文章主要給大家介紹了關(guān)于Spring4如何自定義@Value功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用spring4具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09
  • MyBatis-Plus QueryWrapper及LambdaQueryWrapper的使用詳解

    MyBatis-Plus QueryWrapper及LambdaQueryWrapper的使用詳解

    這篇文章主要介紹了MyBatis-Plus QueryWrapper及LambdaQueryWrapper的使用詳解,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03

最新評論

东至县| 灵璧县| 合山市| 通河县| 五寨县| 阳新县| 马山县| 汕头市| 远安县| 商河县| 福安市| 南城县| 左云县| 昌江| 当雄县| 瑞丽市| 自治县| 昌邑市| 宝清县| 武隆县| 中阳县| 岑巩县| 沂源县| 大埔区| 江西省| 泌阳县| 长白| 宁南县| 永嘉县| 吴堡县| 金溪县| 江川县| 萍乡市| 桂阳县| 桓仁| 淮北市| 城步| 红桥区| 宝丰县| 西乌| 五原县|