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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

那些年,我们追过的java8

發布時間:2025/3/15 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 那些年,我们追过的java8 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
那些年,我們追過的java8

9月份java9就要發布了,在8月的最后一天決定回顧一下java8那些驚天動地的變化,加深理解,共同進步。

我們都知道java與c++,c不同是一個為面向對象而生的語言,面向對象思想貫徹了java發展的大部分時間直到java8,java8的出現為java引進了新的思想(雖然這個思想在別的語言里早就有了)--函數式編程,這是兩種思想的碰撞,導致剛剛接觸java8會覺得自己不是在寫java代碼。。。好了廢話不多說,先總結java8的一些顛覆性的變動點:

1.接口允許有實現:

public interface MyInterface {default String getResult(){return "hello world!";} }

這叫默認實現,據說是為了foreach而引進的,默認方法實現帶來了另一個問題--多重繼承,但是又不是完全意義上的多重繼承,因為繼承的是方法,相當于無狀態多重繼承。所以必須有一些規則來處理多重繼承所帶來的問題:

  • 繼承最近的接口的默認方法。
  • 使用重寫后的方法
  • 當使用以上規則后仍無法確認時,會報錯

2.集合

java8對集合的處理才是重頭戲。先來看看幾個常見的函數式接口:

Consumer

Supplier

Operator

Function

以及在此基礎上的一些擴展

BiConsumer

BinrayOperator

BiFunction

接口就不一一介紹,可以看一下源碼,也很簡單,就是定義了函數的處理方式抽象了各種不同的函數

集合中最常用的工具類:Collectors是本次分析的主角。

在看Collectors類之前,必須先看看一個接口:Collector

它有三個類型:入參類型,中間類型,出參類型,這個接口是干什么的呢,通過它定義的參數,我們基本上可以猜到,它定義了一系列函數,將入參經過一系列處理,變化,得到另一個結果。源碼上有一系列注釋,說明了這個類的作用,這里簡單翻譯一下:

Collector是一個由4個函數組成的,用來做相當于reduce的惰性求值的類。這4個函數是:

Supplier<A> supplier();--用來生成存放惰性求值結果的容器 BiConsumer<A, T> accumulator();--用來計算入參,并將結果放入容器的函數 BinaryOperator<A> combiner();--用來將兩個容器合并成一個容器。(這個是一個fork/join的一個重要步驟) Function<A, R> finisher();--將容器中結果轉化為想要的結果的函數。
其實它還有第5個參數,表明COllector是線程安全的還是不安全的或者A就是R不需要最后一步。

Collector就介紹到這里,在Collectors里有Collector的默認實現。

Collectors里面定義了諸多工具方法,不過,為了展示函數式編程的魅力,我們挑一個長一點的出來分析一把:groupingBy方法,源碼如下:
public static <T, K, D, A, M extends Map<K, D>>Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,Supplier<M> mapFactory,Collector<? super T, A, D> downstream) {Supplier<A> downstreamSupplier = downstream.supplier(); //獲取downstream的容器函數BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator(); //獲取downstream的reduce操作的計算函數BiConsumer<Map<K, A>, T> accumulator = (m, t) -> { //將計算結果放入map中的函數(也是新的collector的計算函數)K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");A container = m.computeIfAbsent(key, k -> downstreamSupplier.get()); //這步是關鍵,通過map的key來判斷是不是同一類,如果是同一類,則返回原來的容器,否則則使用downstream的函數創建一個容器downstreamAccumulator.accept(container, t); //為容器填充值};BinaryOperator<Map<K, A>> merger = Collectors.<K, A, Map<K, A>>mapMerger(downstream.combiner()); //獲取合并函數@SuppressWarnings("unchecked")Supplier<Map<K, A>> mangledFactory = (Supplier<Map<K, A>>) mapFactory; //該函數返回結果容器函數(Map類型)if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) { //如果downstream的類型是IDENTITY_FINISH那么返回新的collectorreturn new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID);}else {@SuppressWarnings("unchecked")Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher(); //否則獲取計算結果的函數Function<Map<K, A>, M> finisher = intermediate -> { //生成新的結果函數intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));@SuppressWarnings("unchecked")M castResult = (M) intermediate;return castResult;};return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID);}}

先看注釋中的一段例子:

Map<Department, Integer> totalByDept= employees.stream().collect(Collectors.groupingBy(Employee::getDepartment,Collectors.summingInt(Employee::getSalary)));

這個例子是計算公司每個部門員工工資綜合,具體的pojo就不給不來了。

縱觀整個過程,groupingBy將downstream(Collector)(直譯:下游流)按照classfier的規則分類,將結果放入由mapFactory函數生成的Map容器中,返回新的Collector。我們看到,如何由一個老的Collector經過一系列處理,變為新的Collector,其實至此仍未結束,我們仍可以對
新的Collector做更多操作,這些操作都不會發生,直到我們調用了及早求值的方法,真正的操作才會發生,如上面的stream.collect,函數式編程操作的不再是數據,而是一個個函數,可以看做一個函數對另一個函數的裝飾從而形成新的函數。
總之,函數式編程已經不僅僅是思想,也是一種編程習慣,如果我們不用,不寫,即使說再多,也是紙上談兵。
java8還是要更多練習與探索的。
java9迎接你的到來。







posted on 2017-08-31 17:47 在山的那邊 閱讀(...) 評論(...) 編輯 收藏

轉載于:https://www.cnblogs.com/foreveravalon/p/7459529.html

總結

以上是生活随笔為你收集整理的那些年,我们追过的java8的全部內容,希望文章能夠幫你解決所遇到的問題。

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