Chapter 14 . JDK8新特性

閱讀原文

Chapter 14 . JDK8新特性

14.1 Lambda 表達(dá)式

Lambda 是一個(gè)匿名函數(shù),我們可以把 Lambda
表達(dá)式理解為是一段可以傳遞的代碼(將代碼
像數(shù)據(jù)一樣進(jìn)行傳遞)??梢詫懗龈啙?、更
靈活的代碼。作為一種更緊湊的代碼風(fēng)格,使
Java的語言表達(dá)能力得到了提升

?

image

image

Lambda 表達(dá)式語法

Lambda 表達(dá)式在Java 語言中引入了一個(gè)新的語法元
素和操作符。這個(gè)操作符為 “->” , 該操作符被稱
為 Lambda 操作符或剪頭操作符。它將 Lambda 分為
兩個(gè)部分:
左側(cè): 指定了 Lambda 表達(dá)式需要的所有參數(shù)
右側(cè): 指定了 Lambda 體,即 Lambda 表達(dá)式要執(zhí)行
的功能

image
image

類型推斷

  • 上述 Lambda 表達(dá)式中的參數(shù)類型都是由編譯器推斷得出的。

  • Lambda 表達(dá)式中無需指定類型,程序依然可以編譯,這是因?yàn)?javac 根據(jù)程序的上下文,在后臺
    推斷出了參數(shù)的類型。

  • Lambda 表達(dá)式的類型依賴于上
    下文環(huán)境,是由編譯器推斷出來的。這就是所謂的
    “類型推斷”


14.2 函數(shù)式接口

只包含一個(gè)抽象方法的接口,稱為函數(shù)式接口。

  • 你可以通過 Lambda 表達(dá)式來創(chuàng)建該接口的對象。(若 Lambda
    表達(dá)式拋出一個(gè)受檢異常,那么該異常需要在目標(biāo)接口的抽象方
    法上進(jìn)行聲明)。

  • 我們可以在任意函數(shù)式接口上使用 @FunctionalInterface 注解,
    這樣做可以檢查它是否是一個(gè)函數(shù)式接口,同時(shí) javadoc 也會包
    含一條聲明,說明這個(gè)接口是一個(gè)函數(shù)式接口。

    image
image
image
image

14.3 方法引用與構(gòu)造器引用

當(dāng)要傳遞給Lambda體的操作,已經(jīng)有實(shí)現(xiàn)的方法了,可以使用方法引用!

(實(shí)現(xiàn)抽象方法的參數(shù)列表,必須與方法引用方法的參數(shù)列表保持一致! )
方法引用:使用操作符 “::” 將方法名和對象或類的名字分隔開來。

如下三種主要使用情況:

  • 對象::實(shí)例方法

  • 類::靜態(tài)方法

  • 類::實(shí)例方法

image
image
image
image

14.4 Stream API

Java8中有兩大最為重要的改變。第一個(gè)是 Lambda 表達(dá)式;另外一
個(gè)則是 Stream API(java.util.stream.*)。

Stream 是 Java8 中處理集合的關(guān)鍵抽象概念,它可以指定你希望對
集合進(jìn)行的操作,可以執(zhí)行非常復(fù)雜的查找、過濾和映射數(shù)據(jù)等操作。

使用Stream API 對集合數(shù)據(jù)進(jìn)行操作,就類似于使用 SQL 執(zhí)行的數(shù)
據(jù)庫查詢。也可以使用 Stream API 來并行執(zhí)行操作。簡而言之,
Stream API 提供了一種高效且易于使用的處理數(shù)據(jù)的方式。

流(Stream) 到底是什么呢?

是數(shù)據(jù)渠道,用于操作數(shù)據(jù)源(集合、數(shù)組等)所生成的元素序列。

“集合講的是數(shù)據(jù),流講的是計(jì)算! ”

注意:

①Stream 自己不會存儲元素。

②Stream 不會改變源對象。相反,他們會返回一個(gè)持有結(jié)果的新Stream。

③Stream 操作是延遲執(zhí)行的。這意味著他們會等到需要結(jié)果的時(shí)候才執(zhí)行。

Stream 的操作三個(gè)步驟

  • 創(chuàng)建 Stream

一個(gè)數(shù)據(jù)源(如: 集合、數(shù)組), 獲取一個(gè)流

  • 中間操作

一個(gè)中間操作鏈,對數(shù)據(jù)源的數(shù)據(jù)進(jìn)行處理

  • 終止操作(終端操作)
    一個(gè)終止操作,執(zhí)行中間操作鏈,并產(chǎn)生結(jié)果

創(chuàng)建 Stream

Java8 中的 Collection 接口被擴(kuò)展,提供了
兩個(gè)獲取流的方法:

  • default Stream<E> stream() : 返回一個(gè)順序流

  • default Stream<E> parallelStream() : 返回一個(gè)并行流

由數(shù)組創(chuàng)建流

Java8 中的 Arrays 的靜態(tài)方法 stream() 可以獲取數(shù)組流:

static <T> Stream<T> stream(T[] array): 返回一個(gè)流

重載形式,能夠處理對應(yīng)基本類型的數(shù)組:

public static IntStream stream(int[] array)
  
public static LongStream stream(long[] array)
 
public static DoubleStream stream(double[] array)

由值創(chuàng)建流

可以使用靜態(tài)方法 Stream.of(), 通過顯示值創(chuàng)建一個(gè)流。它可以接收任意數(shù)量的參數(shù)。

public static<T> Stream<T> of(T... values) : 返回一個(gè)流

由函數(shù)創(chuàng)建流:創(chuàng)建無限流

可以使用靜態(tài)方法 Stream.iterate() 和
Stream.generate(), 創(chuàng)建無限流。

  • 迭代

public static<T> Stream<T> iterate(final T seed, final
UnaryOperator<T> f)

  • 生成

public static<T> Stream<T> generate(Supplier<T> s) :


14.5 Stream 的中間操作

多個(gè)中間操作可以連接起來形成一個(gè)流水線,除非流水
線上觸發(fā)終止操作,否則中間操作不會執(zhí)行任何的處理!
而在終止操作時(shí)一次性全部處理,稱為“惰性求值” 。

image
image
image

14.6 Stream 的終止操作

終端操作會從流的流水線生成結(jié)果。

其結(jié)果可以是任何不是流的
值,例如: List、 Integer,甚至是 void 。

image
image
image
image
image

14.7 并行流與串行流

并行流就是把一個(gè)內(nèi)容分成多個(gè)數(shù)據(jù)塊,并用不同的線程分
別處理每個(gè)數(shù)據(jù)塊的流。
Java 8 中將并行進(jìn)行了優(yōu)化,我們可以很容易的對數(shù)據(jù)進(jìn)行并
行操作。 Stream API 可以聲明性地通過 parallel() 與
sequential() 在并行流與順序流之間進(jìn)行切換。


14.8 了解 Fork/Join 框架

Fork/Join 框架: 就是在必要的情況下,將一個(gè)大任務(wù),進(jìn)行拆分(fork)成若干個(gè)
小任務(wù)(拆到不可再拆時(shí)),再將一個(gè)個(gè)的小任務(wù)運(yùn)算的結(jié)果進(jìn)行 join 匯總.

image

Fork/Join 框架與傳統(tǒng)線程池的區(qū)別

采用 “工作竊取”模式(work-stealing): 當(dāng)執(zhí)行新的任務(wù)時(shí)它可以將其拆分分成更小的任務(wù)執(zhí)行,并將小任務(wù)加到線 程隊(duì)列中,然后再從一個(gè)隨機(jī)線程的隊(duì)列中偷一個(gè)并把它放在自己的隊(duì)列中。

相對于一般的線程池實(shí)現(xiàn),fork/join框架的優(yōu)勢體現(xiàn)在對其中包含的任務(wù)的 處理方式上.在一般的線程池中,如果一個(gè)線程正在執(zhí)行的任務(wù)由于某些原因 無法繼續(xù)運(yùn)行,那么該線程會處于等待狀態(tài).

而在fork/join框架實(shí)現(xiàn)中,如果 某個(gè)子問題由于等待另外一個(gè)子問題的完成而無法繼續(xù)運(yùn)行.那么處理該子 問題的線程會主動(dòng)尋找其他尚未運(yùn)行的子問題來執(zhí)行.這種方式減少了線程 的等待時(shí)間,提高了性能.


14.9 新時(shí)間日期 API

使用 LocalDate、 LocalTime、 LocalDateTime

LocalDate、 LocalTime、 LocalDateTime 類的實(shí)
例是不可變的對象,分別表示使用 ISO-8601日
歷系統(tǒng)的日期、時(shí)間、日期和時(shí)間。它們提供
了簡單的日期或時(shí)間,并不包含當(dāng)前的時(shí)間信
息。也不包含與時(shí)區(qū)相關(guān)的信息。
注: ISO-8601日歷系統(tǒng)是國際標(biāo)準(zhǔn)化組織制定的現(xiàn)代公民的日期和時(shí)間的表示法

image

Instant 時(shí)間戳

用于“時(shí)間戳”的運(yùn)算。它是以Unix元年(傳統(tǒng)
的設(shè)定為UTC時(shí)區(qū)1970年1月1日午夜時(shí)分)開始
所經(jīng)歷的描述進(jìn)行運(yùn)算

Duration 和 Period

Duration:用于計(jì)算兩個(gè)“時(shí)間”間隔
Period:用于計(jì)算兩個(gè)“日期”間隔

日期的操縱

TemporalAdjuster : 時(shí)間校正器。有時(shí)我們可能需要獲
取例如:將日期調(diào)整到“下個(gè)周日”等操作。
l TemporalAdjusters : 該類通過靜態(tài)方法提供了大量的常
用 TemporalAdjuster 的實(shí)現(xiàn)。
例如獲取下個(gè)周日:

image

解析與格式化

java.time.format.DateTimeFormatter 類:該類提供了三種
格式化方法:

  • 預(yù)定義的標(biāo)準(zhǔn)格式

  • 語言環(huán)境相關(guān)的格式

  • 自定義的格式

時(shí)區(qū)的處理

Java8 中加入了對時(shí)區(qū)的支持,帶時(shí)區(qū)的時(shí)間為分別為:

ZonedDate、 ZonedTime、 ZonedDateTime

其中每個(gè)時(shí)區(qū)都對應(yīng)著 ID,地區(qū)ID都為 “{區(qū)域}/{城市}”的格式

例如 : Asia/Shanghai 等

ZoneId:該類中包含了所有的時(shí)區(qū)信息

getAvailableZoneIds() : 可以獲取所有時(shí)區(qū)時(shí)區(qū)信息

of(id) : 用指定的時(shí)區(qū)信息獲取 ZoneId 對象

與傳統(tǒng)日期處理的轉(zhuǎn)換

image

14.10 接口中的默認(rèn)方法與靜態(tài)方法

Java 8中允許接口中包含具有具體實(shí)現(xiàn)的方法,該方法稱為
“默認(rèn)方法”,默認(rèn)方法使用 default 關(guān)鍵字修飾。

image

接口默認(rèn)方法的” 類優(yōu)先” 原則

若一個(gè)接口中定義了一個(gè)默認(rèn)方法,而另外一個(gè)父類或接口中
又定義了一個(gè)同名的方法時(shí)

  • 選擇父類中的方法。如果一個(gè)父類提供了具體的實(shí)現(xiàn),那么
    接口中具有相同名稱和參數(shù)的默認(rèn)方法會被忽略。

  • 接口沖突。如果一個(gè)父接口提供一個(gè)默認(rèn)方法,而另一個(gè)接
    口也提供了一個(gè)具有相同名稱和參數(shù)列表的方法(不管方法
    是否是默認(rèn)方法), 那么必須覆蓋該方法來解決沖突

image

接口中的靜態(tài)方法

Java8 中,接口中允許添加靜態(tài)方法。

image

14.11 其他新特性

Optional 類

Optional<T> 類(java.util.Optional) 是一個(gè)容器類,代表一個(gè)值存在或不存在, 原來用 null 表示一個(gè)值不存在,現(xiàn)在 Optional 可以更好的表達(dá)這個(gè)概念。并且 可以避免空指針異常。

常用方法:

 Optional.of(T t) : 創(chuàng)建一個(gè) Optional 實(shí)例

 Optional.empty() : 創(chuàng)建一個(gè)空的 Optional 實(shí)例

 Optional.ofNullable(T t):若 t 不為 null,創(chuàng)建 Optional 實(shí)例,否則創(chuàng)建空實(shí)例

 isPresent() : 判斷是否包含值

 orElse(T t) : 如果調(diào)用對象包含值,返回該值,否則返回t

 orElseGet(Supplier s) :如果調(diào)用對象包含值,返回該值,否則返回 s 獲取的值

 map(Function f): 如果有值對其處理,并返回處理后的Optional,否則返回 Optional.empty()

 flatMap(Function mapper):與 map 類似,要求返回值必須是Optional

重復(fù)注解與類型注解

Java 8對注解處理提供了兩點(diǎn)改進(jìn):可重復(fù)的注解及可用于類
型的注解。

image
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 對于Java開發(fā)者來說,Java8的版本顯然是一個(gè)具有里程碑意義的版本,蘊(yùn)含了許多令人激動(dòng)的新特性,如果能利用好這...
    huanfuan閱讀 622評論 0 9
  • Java 8的新特性可以幫助你: 1.使用Java 8可以減少冗長的代碼,讓代碼更易于理解 2.通過方法引用和St...
    Phoenix小彬閱讀 1,035評論 0 2
  • 對于Java開發(fā)者來說,Java8的版本顯然是一個(gè)具有里程碑意義的版本,蘊(yùn)含了許多令人激動(dòng)的新特性,如果能利用好這...
    jackcooper閱讀 1,085評論 0 6
  • 原創(chuàng)文章&經(jīng)驗(yàn)總結(jié)&從校招到A廠一路陽光一路滄桑 詳情請戳www.codercc.com 對于Java開發(fā)者來說,...
    你聽___閱讀 2,387評論 4 38
  • 你拍了很多運(yùn)動(dòng)的照片,卻總是感覺太平淡,沒有視覺沖擊力,不夠刺激,怎么辦? 今天我來為你分享一個(gè)小技巧,三分鐘讓你...
    朱子先生的攝影思維閱讀 3,121評論 16 44

友情鏈接更多精彩內(nèi)容