亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

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

2024-07-13 10:14:05
字體:
來源:轉載
供稿:網友

前言

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

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

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

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

generate 與 Supplier

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

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

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

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

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

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

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

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

forEach 與 Consumer

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

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

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

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

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

或者通過方法引用進一步簡化:

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

reduce 與 BinaryOperator

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

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

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

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

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

map 與 Function

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

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

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

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

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

filter 與 Predicate

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

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

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

// 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 方法,它允許我們自定義比較規則對 stream 中的元素排序。與 sorted 搭配的函數式接口是 Comparator,Comparator<T> 使用 int compare(T o1, T o2) 方法比較兩個 T 類型的對象。排序正是通過比較對象之間的相對大小實現的。

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

// 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 的結構,但是要保證 returnValue 是 int 類型。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩福利电影| 欧美另类极品videosbestfree| 欧美性生活大片免费观看网址| 国产综合香蕉五月婷在线| 久久久久久国产免费| 国产91九色视频| 一区二区三区日韩在线| 亚洲国产成人爱av在线播放| 久久欧美在线电影| 在线观看欧美日韩| 18性欧美xxxⅹ性满足| 久久综合色影院| 欧美在线观看网站| 国产精品第七影院| 欧美午夜电影在线| 亚洲精品美女久久久| 欧美寡妇偷汉性猛交| 欧美日韩xxxxx| 清纯唯美亚洲综合| 国产婷婷97碰碰久久人人蜜臀| 红桃视频成人在线观看| 亚洲美女在线视频| 精品成人在线视频| 午夜精品久久久久久久久久久久| 国产91ⅴ在线精品免费观看| 久久精品青青大伊人av| 久久久久久久久久久久av| 尤物tv国产一区| 国产成人久久精品| 精品亚洲国产视频| 亚洲精品按摩视频| 亚洲第一区中文字幕| 91av福利视频| 91精品久久久久久久久久久| 亚洲欧美日韩爽爽影院| 亚洲天堂av女优| 国产精品夜间视频香蕉| 久久久久久有精品国产| 欧美一区二区三区四区在线| 国产精品电影久久久久电影网| 91av视频导航| 亚洲美女www午夜| 久久综合伊人77777| 欧美理论在线观看| 日韩综合视频在线观看| 日韩视频在线免费| 成人欧美一区二区三区黑人| 亚洲第一av网站| 91av在线免费观看视频| 91九色国产社区在线观看| 午夜精品久久久久久久男人的天堂| 久久久av一区| 黑人巨大精品欧美一区免费视频| 亚洲性视频网站| 亚洲精品一区二区网址| 久久激情视频久久| 午夜精品久久久久久久男人的天堂| 精品美女久久久久久免费| 日韩欧美一区视频| 亚洲乱码一区av黑人高潮| 96sao精品视频在线观看| 两个人的视频www国产精品| 日韩动漫免费观看电视剧高清| 日韩精品高清视频| 亚洲人成绝费网站色www| 成人黄色av免费在线观看| 97超视频免费观看| 成人免费网站在线观看| 日韩av高清不卡| 国产69久久精品成人| 久久九九精品99国产精品| 高清欧美性猛交xxxx黑人猛交| 欧美成人sm免费视频| 亚洲精品国产精品国产自| 欧美成aaa人片在线观看蜜臀| 欧美成人免费观看| 国产成人精品999| 久久人人爽人人爽人人片av高请| 久久久久国产精品免费网站| 成人午夜高潮视频| 色综合色综合网色综合| 日韩av中文字幕在线播放| 日韩免费观看av| 久久久久久久一区二区三区| 在线成人免费网站| 日本精品在线视频| 国产精品久久久久久亚洲影视| 色中色综合影院手机版在线观看| 国产精品自拍视频| 亚洲免费影视第一页| 色999日韩欧美国产| 伊人久久久久久久久久久久久| 精品毛片网大全| 97超级碰碰碰久久久| 亚洲综合在线播放| 色樱桃影院亚洲精品影院| 欧美做受高潮电影o| 成人免费视频97| 欧美午夜精品久久久久久浪潮| 97视频在线观看视频免费视频| 欧美成人激情在线| 久久影视电视剧凤归四时歌| 日韩精品视频在线| 琪琪第一精品导航| 国产精品激情av电影在线观看| 国产精品免费电影| 性色av一区二区三区红粉影视| 国内精品一区二区三区| 国产亚洲美女精品久久久| 久久久久久久久久国产精品| 正在播放国产一区| 欧美午夜精品久久久久久人妖| 日韩欧美国产黄色| 亚洲第一视频在线观看| 欧美电影免费观看高清完整| 国产精品美女久久久久久免费| 国产精品亚洲视频在线观看| 91亚洲国产成人久久精品网站| 久久影视电视剧凤归四时歌| 国产精品久久色| 久久久精品国产| 欧美一级视频免费在线观看| 韩曰欧美视频免费观看| 亚洲欧美精品中文字幕在线| 国产999视频| 成人写真福利网| 亚洲欧洲一区二区三区久久| 亚洲精品视频播放| 色婷婷成人综合| 亚洲国产精品va在线看黑人动漫| 日韩欧美一区二区三区| 91亚洲精品在线观看| 97视频网站入口| 精品一区精品二区| 久久久99久久精品女同性| 久久6精品影院| 久久视频免费观看| 亚洲色图15p| 亚洲精品久久久久久久久久久久| 精品亚洲va在线va天堂资源站| 日韩av在线网站| 亚洲精品自拍视频| 亚洲性日韩精品一区二区| 91精品视频在线免费观看| 欧美高清视频一区二区| 欧美日韩亚洲天堂| 亚洲xxxxx电影| 欧美激情精品久久久久久久变态| 91免费人成网站在线观看18| 精品福利在线视频| 欧美日韩国产一区二区三区| 色婷婷综合成人| 91久久久亚洲精品| 亚洲va欧美va国产综合久久| 国产精品免费一区二区三区都可以| 国内免费久久久久久久久久久| 国产视频一区在线| 日韩一区av在线| 日韩少妇与小伙激情| 久久久天堂国产精品女人| 欧美精品手机在线| 在线亚洲午夜片av大片| 久久久久这里只有精品| 日本免费在线精品|