Java8函数式编程(1)--Principle
核心概念
Java8是怎么支持函數編程的呢?主要有三個核心概念:
- 函數接口(Function)
- 流(Stream)
- 聚合器(Collector)
函數接口
關于函數接口,需要記住的就是兩件事:
-
函數接口是行為的抽象;
-
函數接口是數據轉換器。
最直接的支持就是 java.util.Function 包。定義了四個最基礎的函數接口:
- Supplier<T>: 數據提供器,可以提供 T 類型對象;無參的構造器,提供了 get 方法;
- Function<T,R>: 數據轉換器,接收一個 T 類型的對象,返回一個 R類型的對象; 單參數單返回值的行為接口;提供了 apply, compose, andThen, identity 方法;
- Consumer<T>: 數據消費器, 接收一個 T類型的對象,無返回值,通常用于設置T對象的值; 單參數無返回值的行為接口;提供了 accept, andThen 方法;
- Predicate<T>: 條件測試器,接收一個 T 類型的對象,返回布爾值,通常用于傳遞條件函數; 單參數布爾值的條件性接口。提供了 test (條件測試) , and-or- negate(與或非) 方法。
其中, compose, andThen, and, or, negate 用來組合函數接口而得到更強大的函數接口。
其它的函數接口都是通過這四個擴展而來。
- 在參數個數上擴展: 比如接收雙參數的,有 Bi 前綴, 比如 BiConsumer<T,U>, BiFunction<T,U,R> ;
- 在類型上擴展: 比如接收原子類型參數的,有 [Int|Double|Long][Function|Consumer|Supplier|Predicate]
- 特殊常用的變形: 比如 BinaryOperator , 是同類型的雙參數 BiFunction<T,T,T> ,二元操作符 ; UnaryOperator 是 Function<T,T> 一元操作符。
java.util.Function中函數接口整理參考:java.util.function包
聚合器
每一個流式計算的末尾總有一個類似 collect(Collectors.toList()) 的方法調用。collect 是 Stream 的方法,而參數則是聚合器Collector。已有的聚合器定義在Collectors 的靜態方法里。 那么這個聚合器是怎么實現的呢?
Reduce
大部分聚合器都是基于 Reduce 操作實現的。 Reduce ,名曰推導,含有三個要素: 初始值 init, 二元操作符 BinaryOperator, 以及一個用于聚合結果的數據源S。
Reduce 的算法如下:
比如一個列表求和,Sum([1,2,3]) , 那么定義一個初始值 0 以及一個二元加法操作 BO = a + b ,通過三步完成 Reduce 操作:step1: R = 0; step2: v=1, R = 0+v = 1; step2: v=2, R = 1 + v = 3 ; step3: v = 3, R = 3 + v = 6。
四要素
一個聚合器的實現,通常需要提供四要素:
- 一個結果容器的初始值提供器 supplier ;
- 一個用于將每次二元操作的中間結果與結果容器的值進行操作并重新設置結果容器的累積器 accumulator ;
- 一個用于對Stream元素和中間結果進行操作的二元操作符 combiner ;
- 一個用于對結果容器進行最終聚合的轉換器 finisher(可選) 。
流
流(Stream)是Java8對函數式編程的重要支撐。大部分函數式工具都圍繞Stream展開。
Stream的接口
Stream 主要有四類接口:
- 流到流之間的轉換:比如 filter(過濾), map(映射轉換), mapTo[Int|Long|Double] (到原子類型流的轉換), flatMap(高維結構平鋪),flatMapTo[Int|Long|Double], sorted(排序),distinct(不重復值),peek(執行某種操作,流不變,可用于調試),limit(限制到指定元素數量), skip(跳過若干元素) ;
- 流到終值的轉換: 比如 toArray(轉為數組),reduce(推導結果),collect(聚合結果),min(最小值), max(最大值), count (元素個數), anyMatch (任一匹配), allMatch(所有都匹配), noneMatch(一個都不匹配), findFirst(選擇首元素),findAny(任選一元素) ;
- 直接遍歷: forEach (不保序遍歷,比如并行流), forEachOrdered(保序遍歷) ;
- 構造流: empty (構造空流),of (單個元素的流及多元素順序流),iterate (無限長度的有序順序流),generate (將數據提供器轉換成無限非有序的順序流), concat (流的連接), Builder (用于構造流的Builder對象)
除了 Stream 本身自帶的生成Stream 的方法,數組和容器及StreamSupport都有轉換為流的方法。比如 Arrays.stream , [List|Set|Collection].[stream|parallelStream] , StreamSupport.[int|long|double|]stream;
流的類型主要有:Reference(對象流), IntStream (int元素流), LongStream (long元素流), Double (double元素流) ,定義在類 StreamShape 中,主要將操作適配于類型系統。
Reference流相關類
?
?
?
總結
以上是生活随笔為你收集整理的Java8函数式编程(1)--Principle的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java.util.function包
- 下一篇: Java8函数式编程(2)--流与管道