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

歡迎訪問 生活随笔!

生活随笔

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

java

Java8之Stream-函数式接口

發布時間:2024/1/17 java 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java8之Stream-函数式接口 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

實習前只是粗略的看了下Java8的一些基本語法,但是沒有系統的學習過.在使用一段時間后決定系統的對其進行一次分析,加深對Java8函數式編程的理解,提高自己的編碼技巧.另外kotlin崛起,感興趣的朋友嘗試下混編也未嘗不可.


函數式接口

函數式接口,對于Java來說就是接口內只有一個公開方法的接口,因為使用lanbda表達式,例如() -> user.getName()對應的調用則可能是func.get(),編譯器會根據接口推斷所屬于的方法,如果有兩個則無法推斷.Java8提供了很多函數式接口,一般都使用注解@FunctionalInterface聲明,有必要了解如下一些函數式接口.

函數式接口參數類型返回類型描述
SupplierT接收一個T類型的值
ConsumerT處理一個T類型的值
BiConsumerT,U處理T類型和U類型的值
PredicateTboolean處理T類型的值,并返回true或者false.
ToIntFunctionTint處理T類型的值,并返回int值
ToLongFunctionTlong處理T類型的值,并返回long值
ToDoubleFunctionTdouble處理T類型的值,并返回double值
FunctionTR處理T類型的值,并返回R類型值
BiFunctionT,UR處理T類型和U類型的值,并返回R類型值
BiFunctionT,UR處理T類型和U類型的值,并返回R類型值
UnaryOperatorTT處理T類型值,并返回T類型值,
BinaryOperatorT,TT處理T類型值,并返回T類型值

以上的函數每一個代表的都是一種基本的操作,操作之間可以自由組合,所以才有了stream這些靈活的操作.

Stream操作

Stream的操作是建立在函數式接口的組合上的,最好的學習方法是看Stream接口來學習.下面舉一些例子來分析,假設有這樣的一些初始數據.

List<String> testData = new ArrayList<String>();testData.add("張三");testData.add("李四");testData.add("王二");testData.add("麻子");復制代碼

filter

Stream<T> filter(Predicate<? super T> predicate);復制代碼

filter接收predicate函數,predicate是接收T值,返回boolean值,那么對應的引用就可以寫成如下形式,意思是取集合中以'張'開頭的名字.

testData.stream().filter(x -> x.startsWith("張"))復制代碼

map

<R> Stream<R> map(Function<? super T, ? extends R> mapper);復制代碼

map操作接收的是Function接口,對于Function接收T值返回R值,那map的作用就很明顯是轉換用的,比如下面代碼,轉換名稱為對應的名稱長度,也就是從輸入String數據返回int數據.

testData.stream().map(x -> x.length())復制代碼

flatMap

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);復制代碼

flatMap和map都是使用Function接口,不同的是返回值flatMap限定為Stream類型.所以flatMap可以作為合并流使用,如以下代碼,提取出所有的字符.

testData.stream().flatMap(x -> Stream.of(x.split(""))).collect(Collectors.toList());//輸出 [張, 三, 李, 四, 王, 二, 麻, 子]復制代碼

peek

Stream<T> peek(Consumer<? super T> action);復制代碼

peek參數為Consumer,Consumer接收T值,無返回,那么該方法就可以作為調試不影響stream中內容的一些操作,不過由于對象都是地址引用,你再此做一些對象內容操作也是可以的.
reduce

<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);復制代碼

Reduce比較復雜的一個接口,屬于歸納性操作,看參數,第一個是U泛型,也就是輸入類型的參數,最為初始值,第二個BiFunction,接收T,U參數,返回U類型參數,BinaryOperator接收U,U類型,并返回U類型.

StringBuilder identity = new StringBuilder();StringBuilder reduce = testData.stream().flatMap(x -> Stream.of(x.split(""))).reduce(identity, (r, x) -> {r.append(x);return r;}, StringBuilder::append);System.out.println(identity == reduce);System.out.println(reduce.toString());//輸出 true// 張三李四王二麻子復制代碼

首先提供一個基本容器identity,然后兩個參數r即是identity,x為每次輸入參數,最后一個StringBuilder::append是并發下多個identity的合并策略.
再舉個例子,既然reduce屬于歸納性操作,那么也可以當成collect使用,如下:

ArrayList<String> identity = new ArrayList<>();ArrayList<String> result = testData.stream().flatMap(x -> Stream.of(x.split(""))).reduce(identity, (r, x) -> {r.add(x);return r;},(r1,r2) -> {r1.addAll(r2);return r1;});System.out.println(identity == result);System.out.println(result);//輸出 true//[張, 三, 李, 四, 王, 二, 麻, 子]復制代碼

強大的collect

collect無疑是stream中最強大的操作,掌握了collect操作才能說掌握了stream.為了便于使用者,Java提供了Collectors類,該類提供了很多便捷的collect操作,如Collector<T, ?, List<T>> toList(),Collector<T, ?, Set<T>> toSet()等操作.這些操作最終都會調用如下構造函數構造出collector對象,因此掌握該本質是最佳的學習方式.

CollectorImpl(Supplier<A> supplier,BiConsumer<A, T> accumulator,BinaryOperator<A> combiner,Function<A,R> finisher,Set<Characteristics> characteristics) {this.supplier = supplier;this.accumulator = accumulator;this.combiner = combiner;this.finisher = finisher;this.characteristics = characteristics;}復制代碼

Supplier類似reduce中的u,接收一個元數據,BiConsumer則是操作數據,BinaryOperator并發下聚合,finisher完成時的轉換操作,Set應該按照定義是優化一些操作中的轉換.如下面的toList()操作,其finish操作為castingIdentity().

public static <T>Collector<T, ?, List<T>> toList() {return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,(left, right) -> { left.addAll(right); return left; },CH_ID);}復制代碼

再看toMap的實現

public static <T, K, U, M extends Map<K, U>>Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper,BinaryOperator<U> mergeFunction,Supplier<M> mapSupplier) {BiConsumer<M, T> accumulator= (map, element) -> map.merge(keyMapper.apply(element),valueMapper.apply(element), mergeFunction);return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);}復制代碼

Function作為轉換函數提供了key和value的轉換,BinaryOperator提供了重復key合并策略,mapSupplier則表示最終收集到的容器.那么使用就很簡單了

HashMap<Character, String> map = testData.stream().collect(Collectors.toMap(x -> x.charAt(0), Function.identity(), (v1, v2) -> v2, HashMap::new));復制代碼

其他還有很多方法,就不一一敘述,主要是了解這些接口,知道他所擁有的功能,以及組合的意義,即可很好的掌握Java中的函數式編程.

個人博客 mrdear.cn ,歡迎交流

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的Java8之Stream-函数式接口的全部內容,希望文章能夠幫你解決所遇到的問題。

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