日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

跟我学 Java 8 新特性之 Stream 流(三)缩减操作

發布時間:2023/12/3 java 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 跟我学 Java 8 新特性之 Stream 流(三)缩减操作 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自? ?跟我學 Java 8 新特性之 Stream 流(三)縮減操作

和前面兩篇文章一起服用,效果會更佳。通過對流API的基礎體驗Demo和關鍵知識點的講解,相信大家對流API都有一定的認識了,但是流API強大的功能,可不僅僅像前面兩篇文章中說的那樣簡單,大家應該注意到,在第二篇中,我對Stream接口進行介紹的時候,并沒有把他的全部方法都進行了解析說明。

沒錯,從這一篇開始,那些還沒有講解的方法,很可能就開始變成我們的主角了,大家從題目上面應該知道了,本期我們要講的是流API的縮減操作。

何為縮減操作?

我們先考慮一下min()和max(),這兩個方法我們在第一篇和第二篇中均有提到,其中min()是返回流中的最小值,而max()返回流中最大值,前提是他們存在。

他們之間的特點是什么?

①都返回了一個值

②由一可知,他們是終端操作。

如果我們用流API的術語來形容前面這兩種特性的結合體的話,它們代表了縮減操作。因為每個縮減操作都把一個流縮減為一個值,好比最大值,最小值。當然流API,把min()和max(),count()這些操作稱為特例縮減。

即然說到了特例,肯定就有泛化這種概念了,他就是reduce()方法了,其實第二篇當中,他已經出現過了,只是當時我沒有去強調他。

public interface Stream<T> extends BaseStream<T, Stream<T>> {//、、、忽略其他無關緊要的元素 T reduce(T identity, BinaryOperator<T> accumulator); Optional<T> reduce(BinaryOperator<T> accumulator); <U> U reduce(U identity,BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner); }

Stream接口定義了三個版本的reduce(),我們先使用前面兩個,

T reduce(T identity, BinaryOperator<T> accumulator);//1 Optional<T> reduce(BinaryOperator<T> accumulator);//2

第一個版本返回的是一個T類型的對象,T代表的是流中的元素類型!第二個版本是返回一個Optional類型對象。對于這兩種形式,accumulator是一個操作兩個值并得到結果的函數。在第一個版本當中,identity是這樣一個值,對于涉及identity和流中任意的累積操作,得到的結果就是元素自身,沒有任何改變。比如,如果是加法,他就是0,如果是乘法他就是1。

其中的accumulator是一個BinaryOperator的類型,他是java.util.function包中聲明的函數式接口,它擴展了BiFunction函數式接口.

@FunctionalInterface public interface BinaryOperator<T> extends BiFunction<T,T,T> {}@FunctionalInterface public interface BiFunction<T, U, R> {R apply(T t, U u);//notice }

BiFunction接口中的apply()方法的原型在 //notice。其中R指定了結果的類型,T,U分別是第一參數的類型和第二個參數的類型,因此apply()對他的兩個操作數(t,u)應用到同一個函數上,并返回結果,而對BinaryOperator來說,他在擴展 BiFunction時,指定了所有的類型參數都是相同的T,因此對于BinaryOperator函數式接口的apply來說,他也就變成了 T apply(T t, T u),此外,還有一個需要注意的地方是,在應用reduce()時,apply()的第一個參數t,包含的是一個結果,u包含的是下一個元素。在第一次調用時,將取決于使用reduce()的版本,t可能是單位值,或者是前一個元素。

縮減操作的三個約束

  • 無狀態

  • 不干預

  • 關聯性

無狀態,這里可不是LOL的那個無狀態,畢竟他退役了。相信讀過第二篇文章的同學已經很容易理解了,簡單來說無狀態就是每個元素都被單獨地處理,他和流中的其它元素是沒有任何依賴關系的。不干預是指操作數不會改變數據源。最后,操作必須具有關聯性,這里的關聯性是指標準的數學含義,即,給定一個關聯運算符,在一系列操作中使用該運算符,先處理哪一對操作數是無關緊要的。比如,(1 * 2) * 3 <===> 1 * (2 * 3)。?

其中關聯性,在并行流中,是至關重要的。下面我用一個簡單的例子帶著大家實戰一下泛化縮減操作reduce()的使用。

public class Main {public static void main(String[] args) {learnStream();}private static void learnStream() {List<Integer> lists = new ArrayList<>();lists.add(1);lists.add(2);lists.add(3);lists.add(4);lists.add(5);lists.add(6);Optional<Integer> sum = lists.stream().reduce((a, b) -> a + b);if (sum.isPresent()) System.out.println("list的總和為:" + sum.get());//21//<====> lists.stream().reduce((a, b) -> a + b).ifPresent(System.out::println);Integer sum2 = lists.stream().reduce(0, (a, b) -> a + b);//21System.out.println("list的總和為:" + sum2);Optional<Integer> product = lists.stream().reduce((a, b) -> a * b);if (product.isPresent()) System.out.println("list的積為:" + product.get());//720Integer product2 = lists.stream().reduce(1, (a, b) -> a * b);System.out.println("list的積為:" + product2);//720} }

這個Demo主要是計算了一個list里面的總和,積的操作,大家可以和傳統的算總和,積的方法進行對照,比一比衡量一下就有自己的答案了。但是如果你以為流API僅此而已,那你就錯了。

越是后面的東西,就越裝B,我在剛知道他們的時候,反正是被嚇了一跳的,但這些都是后話了,現在我們來詳解一下Demo,并給出擴展的方向:我們這個例子主要是用了lambda表達式對list進行了求和,求積,對于第一個版本為說,求和的時候,identity的值為0,求積的時候它的值為1,強烈建議你們自己感受一下identity的變化對整個結果的變化產生什么 的影響,改變一下identity的值,再運行一下,你就有結果了,另一個擴展點是:

Integer product3 = lists.stream().reduce(1, (a, b) -> {if (b % 2 == 0) return a * b; else return a;//這里你可以為所欲為! });System.out.println("list的偶數的積為:" + product3);//48

小結一下

對于流的縮減操作來說,主要要知道,他只返回一個值,并且它是一個終端操作,然后還有的就是要知道縮減操作的三個約束了,其實最重要的就是無狀態性和關聯性了.這一小節要說的,也就這么多了,應該很容易就把他收到自己的技能樹上面了。

總結

以上是生活随笔為你收集整理的跟我学 Java 8 新特性之 Stream 流(三)缩减操作的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。