国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

這篇具有很好參考價(jià)值的文章主要介紹了Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

目錄

1. Java版本迭代概述

1.1 發(fā)布特點(diǎn)(小步快跑,快速迭代)

1.2 名詞解釋

1.3 各版本支持時(shí)間路線圖

1.4 各版本介紹

1.5 JDK各版本下載鏈接

1.6 如何學(xué)習(xí)新特性

2. Java8新特性:Lambda表達(dá)式

2.1 關(guān)于Java8新特性簡(jiǎn)介

2.2 冗余的匿名內(nèi)部類

2.3 好用的lambda表達(dá)式

2.4 Lambda 及其使用舉例

2.5 語(yǔ)法

2.6 關(guān)于類型推斷

3. Java8新特性:函數(shù)式(Functional)接口

3.1 什么是函數(shù)式接口

3.2 如何理解函數(shù)式接口

3.3 舉例

3.4 Java 內(nèi)置函數(shù)式接口

3.4.1 之前的函數(shù)式接口

3.4.2 四大核心函數(shù)式接口

3.4.3 其它接口

3.4.4 內(nèi)置接口代碼演示

3.4.5 練習(xí)

4. Java8新特性:方法引用與構(gòu)造器引用

4.1 方法引用

4.1.1 方法引用格式

4.1.2 方法引用使用前提

4.1.3 舉例

4.2 構(gòu)造器引用

4.3 數(shù)組構(gòu)造引用

5. Java8新特性:強(qiáng)大的Stream API

5.1 說(shuō)明

5.2 為什么要使用Stream API

5.3 什么是Stream

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

5.4.1 創(chuàng)建Stream實(shí)例

5.4.2 一系列中間操作

5.4.3 終止操作

5.5 Java9新增API

5.6 練習(xí)


1. Java版本迭代概述

1.1 發(fā)布特點(diǎn)(小步快跑,快速迭代)

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

從Java 9 這個(gè)版本開(kāi)始,Java 的計(jì)劃發(fā)布周期是 6個(gè)月

這意味著Java的更新從傳統(tǒng)的以特性驅(qū)動(dòng)的發(fā)布周期,轉(zhuǎn)變?yōu)橐?code>時(shí)間驅(qū)動(dòng)的發(fā)布模式,并且承諾不會(huì)跳票。通過(guò)這樣的方式,開(kāi)發(fā)團(tuán)隊(duì)可以把一些關(guān)鍵特性盡早合并到 JDK 之中,以快速得到開(kāi)發(fā)者反饋,在一定程度上避免出現(xiàn)像 Java 9 兩次被迫延遲發(fā)布的窘?jīng)r。

針對(duì)企業(yè)客戶的需求,Oracle 將以三年為周期發(fā)布長(zhǎng)期支持版本(long term support)。

Oracle 的官方觀點(diǎn)認(rèn)為:與 Java 7->8->9 相比,Java 9->10->11的升級(jí)和 8->8u20->8u40 更相似。

新模式下的 Java 版本發(fā)布都會(huì)包含許多變更,包括語(yǔ)言變更JVM 變更,這兩者都會(huì)對(duì) IDE、字節(jié)碼庫(kù)和框架產(chǎn)生重大影響。此外,不僅會(huì)新增其他 API,還會(huì)有 API被刪除(這在 Java 8 之前沒(méi)有發(fā)生過(guò))。

目前看這種發(fā)布策略是非常成功的,解開(kāi)了 Java/JVM 演進(jìn)的許多枷鎖,至關(guān)重要的是,OpenJDK 的權(quán)力中心,正在轉(zhuǎn)移到開(kāi)發(fā)社區(qū)和開(kāi)發(fā)者手中。在新的模式中,既可以利用 LTS 滿足企業(yè)長(zhǎng)期可靠支持的需求,也可以滿足各種開(kāi)發(fā)者對(duì)于新特性迭代的訴求。因?yàn)橛?2-3 年的最小間隔粒度來(lái)試驗(yàn)一個(gè)特性,基本是不現(xiàn)實(shí)的。

1.2 名詞解釋

名詞解釋:Oracle JDK和Open JDK

這兩個(gè)JDK最大不同就是許可證不一樣。但是對(duì)于個(gè)人用戶來(lái)講,沒(méi)區(qū)別。 ?Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

名詞解釋:JEP

JEP(JDK Enhancement Proposals):jdk 改進(jìn)提案,每當(dāng)需要有新的設(shè)想時(shí)候,JEP可以提出非正式的規(guī)范(specification),被正式認(rèn)可的JEP正式寫(xiě)進(jìn)JDK的發(fā)展路線圖并分配版本號(hào)。

名詞解釋:LTS

LTS(Long-term Support)即長(zhǎng)期支持。Oracle官網(wǎng)提供了對(duì)Oracle JDK個(gè)別版本的長(zhǎng)期支持,即使發(fā)發(fā)行了新版本,比如目前最新的JDK19,在結(jié)束日期前,LTS版本都會(huì)被長(zhǎng)期支持。(出了bug,會(huì)被修復(fù),非LTS則不會(huì)再有補(bǔ)丁發(fā)布)所以,一定要選一個(gè)LTS版本,不然出了漏洞沒(méi)人修復(fù)了。

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

如果要選擇Oracle JDK,目前可選的LTS版本為8、11、17三個(gè)。

1.3 各版本支持時(shí)間路線圖

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

1.4 各版本介紹

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

jdk 9

Java 9 提供了超過(guò)150項(xiàng)新功能特性,包括備受期待的模塊化系統(tǒng)、可交互的 REPL 工具:jshell,JDK 編譯工具,Java 公共 API 和私有代碼,以及安全增強(qiáng)、擴(kuò)展提升、性能管理改善等。

特性太多,查看鏈接:

JDK 9https://openjdk.java.net/projects/jdk9/ jdk 10

JDK 10https://openjdk.java.net/projects/jdk/10/

286: Local-Variable Type Inference 局部變量類型推斷

296: Consolidate the JDK Forest into a Single Repository JDK庫(kù)的合并

304: Garbage-Collector Interface 統(tǒng)一的垃圾回收接口

307: Parallel Full GC for G1 為G1提供并行的Full GC

310: Application Class-Data Sharing 應(yīng)用程序類數(shù)據(jù)(AppCDS)共享

312: Thread-Local Handshakes ThreadLocal握手交互

313: Remove the Native-Header Generation Tool (javah) 移除JDK中附帶的javah工具

314: Additional Unicode Language-Tag Extensions 使用附加的Unicode語(yǔ)言標(biāo)記擴(kuò)展

316: Heap Allocation on Alternative Memory Devices 能將堆內(nèi)存占用分配給用戶指定的備用內(nèi)存設(shè)備

317: Experimental Java-Based JIT Compiler 使用Graal基于Java的編譯器

319: Root Certificates 根證書(shū)

322: Time-Based Release Versioning 基于時(shí)間定于的發(fā)布版本

jdk 11

JDK 11https://openjdk.java.net/projects/jdk/11/

181: Nest-Based Access Control 基于嵌套的訪問(wèn)控制

309: Dynamic Class-File Constants 動(dòng)態(tài)類文件常量

315: Improve Aarch64 Intrinsics 改進(jìn) Aarch64 Intrinsics

318: Epsilon: A No-Op Garbage Collector Epsilon — 一個(gè)No-Op(無(wú)操作)的垃圾收集器 320: Remove the Java EE and CORBA Modules 刪除 Java EE 和 CORBA 模塊

321: HTTP Client (Standard) HTTPClient API

323: Local-Variable Syntax for Lambda Parameters 用于 Lambda 參數(shù)的局部變量語(yǔ)法

324: Key Agreement with Curve25519 and Curve448 Curve25519 和 Curve448 算法的密鑰協(xié)議

327: Unicode 10

328: Flight Recorder 飛行記錄儀

329: ChaCha20 and Poly1305 Cryptographic Algorithms ChaCha20 和 Poly1305 加密算法 330: Launch Single-File Source-Code Programs 啟動(dòng)單一文件的源代碼程序

331: Low-Overhead Heap Profiling 低開(kāi)銷的 Heap Profiling

332: Transport Layer Security (TLS) 1.3 支持 TLS 1.3

333: ZGC: A Scalable Low-Latency Garbage Collector ???(Experimental) 可伸縮低延遲垃圾收集器

335: Deprecate the Nashorn JavaScript Engine 棄用 Nashorn JavaScript 引擎

336: Deprecate the Pack200 Tools and API 棄用 Pack200 工具和 API

jdk 12

JDK 12https://openjdk.java.net/projects/jdk/12/

189:Shenandoah: A Low-Pause-Time Garbage Collector (Experimental) 低暫停時(shí)間的GC 230: Microbenchmark Suite 微基準(zhǔn)測(cè)試套件

325: Switch Expressions (Preview) switch表達(dá)式

334: JVM Constants API? JVM常量API

340: One AArch64 Port, Not Two 只保留一個(gè)AArch64實(shí)現(xiàn)

341: Default CDS Archives 默認(rèn)類數(shù)據(jù)共享歸檔文件

344: Abortable Mixed Collections for G1 可中止的G1 Mixed GC

346: Promptly Return Unused Committed Memory from G1 G1及時(shí)返回未使用的已分配內(nèi)存

jdk 13

JDK 13https://openjdk.java.net/projects/jdk/13/

350: Dynamic CDS Archives 動(dòng)態(tài)CDS檔案

351: ZGC: Uncommit Unused Memory ZGC:取消使用未使用的內(nèi)存

353: Reimplement the Legacy Socket API 重新實(shí)現(xiàn)舊版套接字API

354: Switch Expressions (Preview) switch表達(dá)式(預(yù)覽)

355: Text Blocks (Preview) 文本塊(預(yù)覽)

jdk 14

JDK 14https://openjdk.java.net/projects/jdk/14/

305: Pattern Matching for instanceof (Preview) instanceof的模式匹配

343: Packaging Tool (Incubator) 打包工具

345: NUMA-Aware Memory Allocation for G1 G1的NUMA-Aware內(nèi)存分配

349: JFR Event Streaming JFR事件流

352: Non-Volatile Mapped Byte Buffers 非易失性映射字節(jié)緩沖區(qū)

358: Helpful NullPointerExceptions 實(shí)用的NullPointerExceptions

359: Records (Preview) 361: Switch Expressions (Standard) Switch表達(dá)式

362: Deprecate the Solaris and SPARC Ports 棄用Solaris和SPARC端口

363: Remove the Concurrent Mark Sweep (CMS) Garbage Collector 刪除并發(fā)標(biāo)記掃描(CMS)垃圾回收器

364: ZGC on macOS 365: ZGC on Windows

366: Deprecate the ParallelScavenge + SerialOld GC Combination 棄用ParallelScavenge + SerialOld GC組合

367: Remove the Pack200 Tools and API 刪除Pack200工具和API

368: Text Blocks (Second Preview) 文本塊

370: Foreign-Memory Access API (Incubator) 外部存儲(chǔ)器訪問(wèn)API

jdk 15

JDK 15https://openjdk.java.net/projects/jdk/15/

339: Edwards-Curve Digital Signature Algorithm (EdDSA) EdDSA 數(shù)字簽名算法

360: Sealed Classes (Preview) 密封類(預(yù)覽)

371: Hidden Classes 隱藏類

372: Remove the Nashorn JavaScript Engine 移除 Nashorn JavaScript 引擎

373: Reimplement the Legacy DatagramSocket API 重新實(shí)現(xiàn) Legacy DatagramSocket API 374: Disable and Deprecate Biased Locking 禁用偏向鎖定

375: Pattern Matching for instanceof (Second Preview) instanceof 模式匹配(第二次預(yù)覽) 377: ZGC: A Scalable Low-Latency Garbage Collector ZGC:一個(gè)可擴(kuò)展的低延遲垃圾收集器

378: Text Blocks 文本塊

379: Shenandoah: A Low-Pause-Time Garbage Collector Shenandoah:低暫停時(shí)間垃圾收集器

381: Remove the Solaris and SPARC Ports 移除 Solaris 和 SPARC 端口

383: Foreign-Memory Access API (Second Incubator) 外部存儲(chǔ)器訪問(wèn) API(第二次孵化版)

384: Records (Second Preview) Records(第二次預(yù)覽)

385: Deprecate RMI Activation for Removal 廢棄 RMI 激活機(jī)制

jdk 16

JDK 16https://openjdk.java.net/projects/jdk/16/

338: Vector API (Incubator) Vector API(孵化器)

347: Enable C++14 Language Features JDK C++的源碼中允許使用C++14的語(yǔ)言特性

357: Migrate from Mercurial to Git OpenJDK源碼的版本控制從Mercurial (hg) 遷移到git

369: Migrate to GitHub OpenJDK源碼的版本控制遷移到github上

376: ZGC: Concurrent Thread-Stack Processing ZGC:并發(fā)線程處理

380: Unix-Domain Socket Channels Unix域套接字通道

386: Alpine Linux Port 將glibc的jdk移植到使用musl的alpine linux上

387: Elastic Metaspace 彈性元空間

388: Windows/AArch64 Port 移植JDK到Windows/AArch64

389: Foreign Linker API (Incubator) 提供jdk.incubator.foreign來(lái)簡(jiǎn)化native code的調(diào)用

390: Warnings for Value-Based Classes 提供基于值的類的警告

392: Packaging Tool jpackage打包工具轉(zhuǎn)正

393: Foreign-Memory Access API (Third Incubator)

394: Pattern Matching for instanceof Instanceof的模式匹配轉(zhuǎn)正

395: Records Records轉(zhuǎn)正

396: Strongly Encapsulate JDK Internals by Default 默認(rèn)情況下,封裝了JDK內(nèi)部構(gòu)件

397: Sealed Classes (Second Preview) 密封類

jdk 17

JDK 17https://openjdk.java.net/projects/jdk/17/

306: Restore Always-Strict Floating-Point Semantics 恢復(fù)始終嚴(yán)格的浮點(diǎn)語(yǔ)義

356: Enhanced Pseudo-Random Number Generators 增強(qiáng)型偽隨機(jī)數(shù)生成器

382: New macOS Rendering Pipeline 新的macOS渲染管道

391: macOS/AArch64 Port macOS/AArch64端口

398: Deprecate the Applet API for Removal 棄用Applet API后續(xù)將進(jìn)行刪除

403: Strongly Encapsulate JDK Internals 強(qiáng)封裝JDK的內(nèi)部API

406: Pattern Matching for switch (Preview) switch模式匹配(預(yù)覽)

407: Remove RMI Activation 刪除RMI激活機(jī)制

409: Sealed Classes 密封類轉(zhuǎn)正

410: Remove the Experimental AOT and JIT Compiler 刪除實(shí)驗(yàn)性的AOT和JIT編譯器

411: Deprecate the Security Manager for Removal 棄用即將刪除的安全管理器

412: Foreign Function & Memory API (Incubator) 外部函數(shù)和內(nèi)存API(孵化特性)

414: Vector API (Second Incubator) Vector API(第二次孵化特性)

415: Context-Specific Deserialization Filters 上下文特定的反序列化過(guò)濾器

1.5 JDK各版本下載鏈接

?Java Archive | Oraclehttps://www.oracle.com/java/technologies/downloads/archive/

?Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

1.6 如何學(xué)習(xí)新特性

對(duì)于新特性,我們應(yīng)該從哪幾個(gè)角度學(xué)習(xí)新特性呢?

  • 語(yǔ)法層面:

    • 比如JDK5中的自動(dòng)拆箱、自動(dòng)裝箱、enum、泛型

    • 比如JDK8中的lambda表達(dá)式、接口中的默認(rèn)方法、靜態(tài)方法

    • 比如JDK10中局部變量的類型推斷

    • 比如JDK12中的switch

    • 比如JDK13中的文本塊

  • API層面:

    • 比如JDK8中的Stream、Optional、新的日期時(shí)間、HashMap的底層結(jié)構(gòu)

    • 比如JDK9中String的底層結(jié)構(gòu)

    • 新的 / 過(guò)時(shí)的 API

  • 底層優(yōu)化

    • 比如JDK8中永久代被元空間替代、新的JS執(zhí)行引擎

    • 比如新的垃圾回收器、GC參數(shù)、JVM的優(yōu)化

2. Java8新特性:Lambda表達(dá)式

2.1 關(guān)于Java8新特性簡(jiǎn)介

Java 8 (又稱為 JDK 8或JDK1.8) 是 Java 語(yǔ)言開(kāi)發(fā)的一個(gè)主要版本。 Java 8 是oracle公司于2014年3月發(fā)布,可以看成是自Java 5 以來(lái)最具革命性的版本。Java 8為Java語(yǔ)言、編譯器、類庫(kù)、開(kāi)發(fā)工具與JVM帶來(lái)了大量新特性。

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

  • 速度更快

  • 代碼更少(增加了新的語(yǔ)法:Lambda 表達(dá)式)

  • 強(qiáng)大的 Stream API

  • 便于并行

    • 并行流就是把一個(gè)內(nèi)容分成多個(gè)數(shù)據(jù)塊,并用不同的線程分別處理每個(gè)數(shù)據(jù)塊的流。相比較串行的流,并行的流可以很大程度上提高程序的執(zhí)行效率。

    • Java 8 中將并行進(jìn)行了優(yōu)化,我們可以很容易的對(duì)數(shù)據(jù)進(jìn)行并行操作。Stream API 可以聲明性地通過(guò) parallel() 與 sequential() 在并行流與順序流之間進(jìn)行切換。

  • 最大化減少空指針異常:Optional

  • Nashorn引擎,允許在JVM上運(yùn)行JS應(yīng)用

    • 發(fā)音“nass-horn”,是德國(guó)二戰(zhàn)時(shí)一個(gè)坦克的命名

    • javascript運(yùn)行在jvm已經(jīng)不是新鮮事了,Rhino早在jdk6的時(shí)候已經(jīng)存在?,F(xiàn)在替代Rhino,官方的解釋是Rhino相比其他JavaScript引擎(比如google的V8)實(shí)在太慢了,改造Rhino還不如重寫(xiě)。所以Nashorn的性能也是其一個(gè)亮點(diǎn)。

    • Nashorn 項(xiàng)目在 JDK 9 中得到改進(jìn);在JDK11 中Deprecated,后續(xù)JDK15版本中remove。在JDK11中取以代之的是GraalVM。(GraalVM是一個(gè)運(yùn)行時(shí)平臺(tái),它支持Java和其他基于Java字節(jié)碼的語(yǔ)言,但也支持其他語(yǔ)言,如JavaScript,Ruby,Python或LLVM。性能是Nashorn的2倍以上。)

2.2 冗余的匿名內(nèi)部類

當(dāng)需要啟動(dòng)一個(gè)線程去完成任務(wù)時(shí),通常會(huì)通過(guò)java.lang.Runnable接口來(lái)定義任務(wù)內(nèi)容,并使用java.lang.Thread類來(lái)啟動(dòng)該線程。代碼如下:

public class UseFunctionalProgramming {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("多線程任務(wù)執(zhí)行!");
            }
        }).start(); // 啟動(dòng)線程
    }
}

本著“一切皆對(duì)象”的思想,這種做法是無(wú)可厚非的:首先創(chuàng)建一個(gè)Runnable接口的匿名內(nèi)部類對(duì)象來(lái)指定任務(wù)內(nèi)容,再將其交給一個(gè)線程來(lái)啟動(dòng)。

代碼分析:

對(duì)于Runnable的匿名內(nèi)部類用法,可以分析出幾點(diǎn)內(nèi)容:

  • Thread類需要Runnable接口作為參數(shù),其中的抽象run方法是用來(lái)指定線程任務(wù)內(nèi)容的核心;

  • 為了指定run的方法體,不得不需要Runnable接口的實(shí)現(xiàn)類;

  • 為了省去定義一個(gè)RunnableImpl實(shí)現(xiàn)類的麻煩,不得不使用匿名內(nèi)部類;

  • 必須覆蓋重寫(xiě)抽象run方法,所以方法名稱、方法參數(shù)、方法返回值不得不再寫(xiě)一遍,且不能寫(xiě)錯(cuò);

  • 而實(shí)際上,似乎只有方法體才是關(guān)鍵所在。

2.3 好用的lambda表達(dá)式

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

2.4 Lambda 及其使用舉例

Lambda 是一個(gè)匿名函數(shù),我們可以把 Lambda 表達(dá)式理解為是一段可以傳遞的代碼(將代碼像數(shù)據(jù)一樣進(jìn)行傳遞)。使用它可以寫(xiě)出更簡(jiǎn)潔、更靈活的代碼。作為一種更緊湊的代碼風(fēng)格,使Java的語(yǔ)言表達(dá)能力得到了提升。

  • 從匿名類到 Lambda 的轉(zhuǎn)換舉例1

  • Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》?

  • 從匿名類到 Lambda 的轉(zhuǎn)換舉例2

  • Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

    ??

2.5 語(yǔ)法

Lambda 表達(dá)式:在Java 8 語(yǔ)言中引入的一種新的語(yǔ)法元素和操作符。這個(gè)操作符為 “->” , 該操作符被稱為 Lambda 操作符箭頭操作符。它將 Lambda 分為兩個(gè)部分:

  • 左側(cè):指定了 Lambda 表達(dá)式需要的參數(shù)列表,參數(shù)的類型都可以省略(參數(shù)類型推斷),如果形參只有一個(gè),則一對(duì)()也可以省略

  • 右側(cè):指定了 Lambda 體,是抽象方法的實(shí)現(xiàn)邏輯,也即 Lambda 表達(dá)式要執(zhí)行的功能。如果方法體中只有一行語(yǔ)句,可以省略一對(duì){},如果有return關(guān)鍵字則可以一并省略

語(yǔ)法格式一:無(wú)參,無(wú)返回值

@Test
public void test1(){
    //未使用Lambda表達(dá)式
    Runnable r1 = new Runnable() {
        @Override
        public void run() {
            System.out.println("我愛(ài)北京天安門");
        }
    };

    r1.run();

    System.out.println("***********************");

    //使用Lambda表達(dá)式
    Runnable r2 = () -> {
        System.out.println("我愛(ài)北京故宮");
    };

    r2.run();
}

?語(yǔ)法格式二:Lambda 需要一個(gè)參數(shù),但是沒(méi)有返回值

@Test
public void test2(){
    //未使用Lambda表達(dá)式
    Consumer<String> con = new Consumer<String>() {
        @Override
        public void accept(String s) {
            System.out.println(s);
        }
    };
    con.accept("謊言和誓言的區(qū)別是什么?");

    System.out.println("*******************");

    //使用Lambda表達(dá)式
    Consumer<String> con1 = (String s) -> {
        System.out.println(s);
    };
    con1.accept("一個(gè)是聽(tīng)得人當(dāng)真了,一個(gè)是說(shuō)的人當(dāng)真了");

}

語(yǔ)法格式三:數(shù)據(jù)類型可以省略,因?yàn)榭捎删幾g器推斷得出,稱為“類型推斷”

@Test
public void test3(){
    //語(yǔ)法格式三使用前
    Consumer<String> con1 = (String s) -> {
        System.out.println(s);
    };
    con1.accept("一個(gè)是聽(tīng)得人當(dāng)真了,一個(gè)是說(shuō)的人當(dāng)真了");

    System.out.println("*******************");
    //語(yǔ)法格式三使用后
    Consumer<String> con2 = (s) -> {
        System.out.println(s);
    };
    con2.accept("一個(gè)是聽(tīng)得人當(dāng)真了,一個(gè)是說(shuō)的人當(dāng)真了");

}

語(yǔ)法格式四:Lambda 若只需要一個(gè)參數(shù)時(shí),參數(shù)的小括號(hào)可以省略

@Test
public void test4(){
    //語(yǔ)法格式四使用前
    Consumer<String> con1 = (s) -> {
        System.out.println(s);
    };
    con1.accept("一個(gè)是聽(tīng)得人當(dāng)真了,一個(gè)是說(shuō)的人當(dāng)真了");

    System.out.println("*******************");
    //語(yǔ)法格式四使用后
    Consumer<String> con2 = s -> {
        System.out.println(s);
    };
    con2.accept("一個(gè)是聽(tīng)得人當(dāng)真了,一個(gè)是說(shuō)的人當(dāng)真了");


}

語(yǔ)法格式五:Lambda 需要兩個(gè)或以上的參數(shù),多條執(zhí)行語(yǔ)句,并且可以有返回值

@Test
public void test5(){
    //語(yǔ)法格式五使用前
    Comparator<Integer> com1 = new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            System.out.println(o1);
            System.out.println(o2);
            return o1.compareTo(o2);
        }
    };

    System.out.println(com1.compare(12,21));
    System.out.println("*****************************");
    //語(yǔ)法格式五使用后
    Comparator<Integer> com2 = (o1,o2) -> {
        System.out.println(o1);
        System.out.println(o2);
        return o1.compareTo(o2);
    };

    System.out.println(com2.compare(12,6));


}

語(yǔ)法格式六:當(dāng) Lambda 體只有一條語(yǔ)句時(shí),return 與大括號(hào)若有,都可以省略

@Test
public void test6(){
    //語(yǔ)法格式六使用前
    Comparator<Integer> com1 = (o1,o2) -> {
        return o1.compareTo(o2);
    };

    System.out.println(com1.compare(12,6));

    System.out.println("*****************************");
    //語(yǔ)法格式六使用后
    Comparator<Integer> com2 = (o1,o2) -> o1.compareTo(o2);

    System.out.println(com2.compare(12,21));

}

@Test
public void test7(){
    //語(yǔ)法格式六使用前
    Consumer<String> con1 = s -> {
        System.out.println(s);
    };
    con1.accept("一個(gè)是聽(tīng)得人當(dāng)真了,一個(gè)是說(shuō)的人當(dāng)真了");

    System.out.println("*****************************");
    //語(yǔ)法格式六使用后
    Consumer<String> con2 = s -> System.out.println(s);

    con2.accept("一個(gè)是聽(tīng)得人當(dāng)真了,一個(gè)是說(shuō)的人當(dāng)真了");

}

2.6 關(guān)于類型推斷

在語(yǔ)法格式三 Lambda 表達(dá)式中的參數(shù)類型都是由編譯器推斷得出的。Lambda 表達(dá)式中無(wú)需指定類型,程序依然可以編譯,這是因?yàn)?javac 根據(jù)程序的上下文,在后臺(tái)推斷出了參數(shù)的類型。Lambda 表達(dá)式的類型依賴于上下文環(huán)境,是由編譯器推斷出來(lái)的。這就是所謂的“類型推斷”。

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》?

舉例:

@Test
public void test() {
    //類型推斷1
    ArrayList<String> list = new ArrayList<>();
    //類型推斷2
    int[] arr = {1, 2, 3};

}

3. Java8新特性:函數(shù)式(Functional)接口

3.1 什么是函數(shù)式接口

  • 只包含一個(gè)抽象方法(Single Abstract Method,簡(jiǎn)稱SAM)的接口,稱為函數(shù)式接口。當(dāng)然該接口可以包含其他非抽象方法。

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

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

  • java.util.function包下定義了Java 8 的豐富的函數(shù)式接口

3.2 如何理解函數(shù)式接口

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》?

  • Java從誕生日起就是一直倡導(dǎo)“一切皆對(duì)象”,在Java里面面向?qū)ο?OOP)編程是一切。但是隨著python、scala等語(yǔ)言的興起和新技術(shù)的挑戰(zhàn),Java不得不做出調(diào)整以便支持更加廣泛的技術(shù)要求,即Java不但可以支持OOP還可以支持OOF(面向函數(shù)編程)

    • Java8引入了Lambda表達(dá)式之后,Java也開(kāi)始支持函數(shù)式編程。

    • Lambda表達(dá)式不是Java最早使用的。目前C++,C#,Python,Scala等均支持Lambda表達(dá)式。

  • 面向?qū)ο蟮乃枷耄?/p>

    • 做一件事情,找一個(gè)能解決這個(gè)事情的對(duì)象,調(diào)用對(duì)象的方法,完成事情。

  • 函數(shù)式編程思想:

    • 只要能獲取到結(jié)果,誰(shuí)去做的,怎么做的都不重要,重視的是結(jié)果,不重視過(guò)程。

  • 在函數(shù)式編程語(yǔ)言當(dāng)中,函數(shù)被當(dāng)做一等公民對(duì)待。在將函數(shù)作為一等公民的編程語(yǔ)言中,Lambda表達(dá)式的類型是函數(shù)。但是在Java8中,有所不同。在Java8中,Lambda表達(dá)式是對(duì)象,而不是函數(shù),它們必須依附于一類特別的對(duì)象類型——函數(shù)式接口。

  • 簡(jiǎn)單的說(shuō),在Java8中,Lambda表達(dá)式就是一個(gè)函數(shù)式接口的實(shí)例。這就是Lambda表達(dá)式和函數(shù)式接口的關(guān)系。也就是說(shuō),只要一個(gè)對(duì)象是函數(shù)式接口的實(shí)例,那么該對(duì)象就可以用Lambda表達(dá)式來(lái)表示。

3.3 舉例

舉例1:

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》?

舉例2:

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

?作為參數(shù)傳遞 Lambda 表達(dá)式:

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

作為參數(shù)傳遞 Lambda 表達(dá)式:為了將 Lambda 表達(dá)式作為參數(shù)傳遞,接收Lambda 表達(dá)式的參數(shù)類型必須是與該 Lambda 表達(dá)式兼容的函數(shù)式接口的類型。

3.4 Java 內(nèi)置函數(shù)式接口

3.4.1 之前的函數(shù)式接口

之前學(xué)過(guò)的接口,有些就是函數(shù)式接口,比如:

  • java.lang.Runnable

    • public void run()

  • java.lang.Iterable<T>

    • public Iterator<T> iterate()

  • java.lang.Comparable<T>

    • public int compareTo(T t)

  • java.util.Comparator<T>

    • public int compare(T t1, T t2)

3.4.2 四大核心函數(shù)式接口

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

3.4.3 其它接口

類型1:消費(fèi)型接口

消費(fèi)型接口的抽象方法特點(diǎn):有形參,但是返回值類型是void

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

類型2:供給型接口

這類接口的抽象方法特點(diǎn):無(wú)參,但是有返回值

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

類型3:函數(shù)型接口

這類接口的抽象方法特點(diǎn):既有參數(shù)又有返回值

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

類型4:判斷型接口

這類接口的抽象方法特點(diǎn):有參,但是返回值類型是boolean結(jié)果。

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

3.4.4 內(nèi)置接口代碼演示

舉例1:

import java.util.Arrays;
import java.util.List;

public class TestConsumer {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("java","c","python","c++","VB","C#");
        //遍歷Collection集合,并將傳遞給action參數(shù)的操作代碼應(yīng)用在每一個(gè)元素上。
        list.forEach(s -> System.out.println(s));
    }
}

?舉例2:

import java.util.function.Supplier;

public class TestSupplier {
    public static void main(String[] args) {
        Supplier<String> supplier = () -> "尚硅谷";
        System.out.println(supplier.get());
    }
}

?舉例3:

import java.util.ArrayList;

public class TestPredicate {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");
        list.add("atguigu");
        list.add("ok");
        list.add("yes");

        System.out.println("刪除之前:");
        list.forEach(t-> System.out.println(t));
		
        //用于刪除集合中滿足filter指定的條件判斷的。
        //刪除包含o字母的元素
        list.removeIf(s -> s.contains("o"));

        System.out.println("刪除包含o字母的元素之后:");
        list.forEach(t-> System.out.println(t));
    }
}

?舉例4:

import java.util.function.Function;

public class TestFunction {
    public static void main(String[] args) {
        //使用Lambda表達(dá)式實(shí)現(xiàn)Function<T,R>接口,可以實(shí)現(xiàn)將一個(gè)字符串首字母轉(zhuǎn)為大寫(xiě)的功能。
        Function<String,String> fun = s -> s.substring(0,1).toUpperCase() + s.substring(1);
        System.out.println(fun.apply("hello"));
    }
}

3.4.5 練習(xí)

練習(xí)1:無(wú)參無(wú)返回值形式

假如有自定義函數(shù)式接口Call如下:

public interface Call {
    void shout();
}

在測(cè)試類中聲明一個(gè)如下方法:

public static void callSomething(Call call){
        call.shout();
}

在測(cè)試類的main方法中調(diào)用callSomething方法,并用Lambda表達(dá)式為形參call賦值,可以喊出任意你想說(shuō)的話。

public class TestLambda {
	public static void main(String[] args) {
		callSomething(()->System.out.println("回家吃飯"));
		callSomething(()->System.out.println("我愛(ài)你"));
		callSomething(()->System.out.println("滾蛋"));
		callSomething(()->System.out.println("回來(lái)"));
	}
	public static void callSomething(Call call){
		call.shout();
	}
}
interface Call {
    void shout();
}

練習(xí)2:消費(fèi)型接口

代碼示例:Consumer<T>接口

在JDK1.8中Collection集合接口的父接口Iterable接口中增加了一個(gè)默認(rèn)方法:

public default void forEach(Consumer<? super T> action)遍歷Collection集合的每個(gè)元素,執(zhí)行“xxx消費(fèi)型”操作。

在JDK1.8中Map集合接口中增加了一個(gè)默認(rèn)方法:

public default void forEach(BiConsumer<? super K,? super V> action)遍歷Map集合的每對(duì)映射關(guān)系,執(zhí)行“xxx消費(fèi)型”操作。

案例:

(1)創(chuàng)建一個(gè)Collection系列的集合,添加一些字符串,調(diào)用forEach方法遍歷查看

(2)創(chuàng)建一個(gè)Map系列的集合,添加一些(key,value)鍵值對(duì),調(diào)用forEach方法遍歷查看

示例代碼:

	@Test
	public void test1(){
		List<String> list = Arrays.asList("hello","java","lambda","atguigu");
		list.forEach(s -> System.out.println(s));
    }
	@Test
	public void test2(){
		HashMap<Integer,String> map = new HashMap<>();
		map.put(1, "hello");
		map.put(2, "java");
		map.put(3, "lambda");
		map.put(4, "atguigu");
		map.forEach((k,v) -> System.out.println(k+"->"+v));
	}

練習(xí)3:供給型接口

代碼示例:Supplier<T>接口

在JDK1.8中增加了StreamAPI,java.util.stream.Stream<T>是一個(gè)數(shù)據(jù)流。這個(gè)類型有一個(gè)靜態(tài)方法:

`public static <T> Stream<T> generate(Supplier<T> s)`可以創(chuàng)建Stream的對(duì)象。而又包含一個(gè)forEach方法可以遍歷流中的元素:`public void forEach(Consumer<? super T> action)`。

案例:

現(xiàn)在請(qǐng)調(diào)用Stream的generate方法,來(lái)產(chǎn)生一個(gè)流對(duì)象,并調(diào)用Math.random()方法來(lái)產(chǎn)生數(shù)據(jù),為Supplier函數(shù)式接口的形參賦值。最后調(diào)用forEach方法遍歷流中的數(shù)據(jù)查看結(jié)果。

	@Test
	public void test2(){
		Stream.generate(() -> Math.random()).forEach(num -> System.out.println(num));
	}

練習(xí)4:功能型接口

代碼示例:Function<T,R>接口

在JDK1.8時(shí)Map接口增加了很多方法,例如:

public default void replaceAll(BiFunction<? super K,? super V,? extends V> function)按照f(shuō)unction指定的操作替換map中的value。

public default void forEach(BiConsumer<? super K,? super V> action)遍歷Map集合的每對(duì)映射關(guān)系,執(zhí)行“xxx消費(fèi)型”操作。

案例:

(1)聲明一個(gè)Employee員工類型,包含編號(hào)、姓名、薪資。

(2)添加n個(gè)員工對(duì)象到一個(gè)HashMap<Integer,Employee>集合中,其中員工編號(hào)為key,員工對(duì)象為value。

(3)調(diào)用Map的forEach遍歷集合

(4)調(diào)用Map的replaceAll方法,將其中薪資低于10000元的,薪資設(shè)置為10000。

(5)再次調(diào)用Map的forEach遍歷集合查看結(jié)果

Employee類

class Employee{
	private int id;
	private String name;
	private double salary;
	public Employee(int id, String name, double salary) {
		super();
		this.id = id;
		this.name = name;
		this.salary = salary;
	}
	public Employee() {
		super();
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + "]";
	}
	
}

測(cè)試類:

import java.util.HashMap;

public class TestLambda {
	public static void main(String[] args) {
		HashMap<Integer,Employee> map = new HashMap<>();
		Employee e1 = new Employee(1, "張三", 8000);
		Employee e2 = new Employee(2, "李四", 9000);
		Employee e3 = new Employee(3, "王五", 10000);
		Employee e4 = new Employee(4, "趙六", 11000);
		Employee e5 = new Employee(5, "錢七", 12000);
		
		map.put(e1.getId(), e1);
		map.put(e2.getId(), e2);
		map.put(e3.getId(), e3);
		map.put(e4.getId(), e4);
		map.put(e5.getId(), e5);
		
		map.forEach((k,v) -> System.out.println(k+"="+v));
		System.out.println();
		
		map.replaceAll((k,v)->{
			if(v.getSalary()<10000){
				v.setSalary(10000);
			}
			return v;
		});
		map.forEach((k,v) -> System.out.println(k+"="+v));
	}
}

練習(xí)5:判斷型接口

代碼示例:Predicate<T>接口

JDK1.8時(shí),Collecton<E>接口增加了一下方法,其中一個(gè)如下:

public default boolean removeIf(Predicate<? super E> filter) 用于刪除集合中滿足filter指定的條件判斷的。

public default void forEach(Consumer<? super T> action)遍歷Collection集合的每個(gè)元素,執(zhí)行“xxx消費(fèi)型”操作。

案例:

(1)添加一些字符串到一個(gè)Collection集合中

(2)調(diào)用forEach遍歷集合

(3)調(diào)用removeIf方法,刪除其中字符串的長(zhǎng)度<5的

(4)再次調(diào)用forEach遍歷集合

import java.util.ArrayList;

public class TestLambda {
	public static void main(String[] args) {
		ArrayList<String> list = new ArrayList<>();
		list.add("hello");
		list.add("java");
		list.add("atguigu");
		list.add("ok");
		list.add("yes");
		
		list.forEach(str->System.out.println(str));
		System.out.println();
		
		list.removeIf(str->str.length()<5);
		list.forEach(str->System.out.println(str));
	}
}

練習(xí)6:判斷型接口

案例:

(1)聲明一個(gè)Employee員工類型,包含編號(hào)、姓名、性別,年齡,薪資。

(2)聲明一個(gè)EmployeeSerice員工管理類,包含一個(gè)ArrayList<Employee>集合的屬性all,在EmployeeSerice的構(gòu)造器中,創(chuàng)建一些員工對(duì)象,為all集合初始化。

(3)在EmployeeSerice員工管理類中,聲明一個(gè)方法:ArrayList<Employee> get(Predicate<Employee> p),即將滿足p指定的條件的員工,添加到一個(gè)新的ArrayList<Employee> 集合中返回。

(4)在測(cè)試類中創(chuàng)建EmployeeSerice員工管理類的對(duì)象,并調(diào)用get方法,分別獲?。?/p>

  • 所有員工對(duì)象

  • 所有年齡超過(guò)35的員工

  • 所有薪資高于15000的女員工

  • 所有編號(hào)是偶數(shù)的員工

  • 名字是“張三”的員工

  • 年齡超過(guò)25,薪資低于10000的男員工

示例代碼:

Employee類:

public class Employee{
	private int id;
	private String name;
	private char gender;
	private int age;
	private double salary;
	
	public Employee(int id, String name, char gender, int age, double salary) {
		super();
		this.id = id;
		this.name = name;
		this.gender = gender;
		this.age = age;
		this.salary = salary;
	}
	public Employee() {
		super();
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", gender=" + gender + ", age=" + age + ", salary=" + salary
				+ "]";
	}
}

員工管理類:

class EmployeeService{
	private ArrayList<Employee> all;
	public EmployeeService(){
		all = new ArrayList<Employee>();
		all.add(new Employee(1, "張三", '男', 33, 8000));
		all.add(new Employee(2, "翠花", '女', 23, 18000));
		all.add(new Employee(3, "無(wú)能", '男', 46, 8000));
		all.add(new Employee(4, "李四", '女', 23, 9000));
		all.add(new Employee(5, "老王", '男', 23, 15000));
		all.add(new Employee(6, "大嘴", '男', 23, 11000));
	}
	public ArrayList<Employee> get(Predicate<Employee> p){
		ArrayList<Employee> result = new ArrayList<Employee>();
		for (Employee emp : result) {
			if(p.test(emp)){
				result.add(emp);
			}
		}
		return result;
	}
}

測(cè)試類:

public class TestLambda {
	public static void main(String[] args) {
		EmployeeService es = new EmployeeService();
		
		es.get(e -> true).forEach(e->System.out.println(e));
		System.out.println();
		es.get(e -> e.getAge()>35).forEach(e->System.out.println(e));
		System.out.println();
		es.get(e -> e.getSalary()>15000 && e.getGender()=='女').forEach(e->System.out.println(e));
		System.out.println();
		es.get(e -> e.getId()%2==0).forEach(e->System.out.println(e));
		System.out.println();
		es.get(e -> "張三".equals(e.getName())).forEach(e->System.out.println(e));
		System.out.println();
		es.get(e -> e.getAge()>25 && e.getSalary()<10000 && e.getGender()=='男').forEach(e->System.out.println(e));
	}
}

4. Java8新特性:方法引用與構(gòu)造器引用

Lambda表達(dá)式是可以簡(jiǎn)化函數(shù)式接口的變量或形參賦值的語(yǔ)法。而方法引用和構(gòu)造器引用是為了簡(jiǎn)化Lambda表達(dá)式的。

4.1 方法引用

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

方法引用可以看做是Lambda表達(dá)式深層次的表達(dá)。換句話說(shuō)方法引用就是Lambda表達(dá)式,也就是函數(shù)式接口的一個(gè)實(shí)例,通過(guò)方法的名字來(lái)指向一個(gè)方法,可以認(rèn)為是Lambda表達(dá)式的一個(gè)語(yǔ)法糖。

語(yǔ)法糖(Syntactic sugar),也譯為糖衣語(yǔ)法,是由英國(guó)計(jì)算機(jī)科學(xué)家彼得·約翰·蘭達(dá)(Peter J. Landin)發(fā)明的一個(gè)術(shù)語(yǔ),指計(jì)算機(jī)語(yǔ)言中添加的某種語(yǔ)法,這種語(yǔ)法對(duì)語(yǔ)言的功能并沒(méi)有影響,但是更方便程序員使用。通常來(lái)說(shuō)使用語(yǔ)法糖能夠增加程序的可讀性,從而減少程序代碼出錯(cuò)的機(jī)會(huì)。

4.1.1 方法引用格式

  • 格式:使用方法引用操作符 “::” 將類(或?qū)ο? 與 方法名分隔開(kāi)來(lái)。

    • 兩個(gè):中間不能有空格,而且必須英文狀態(tài)下半角輸入

  • 如下三種主要使用情況:

    • 情況1:對(duì)象 :: 實(shí)例方法名

    • 情況2:類 :: 靜態(tài)方法名

    • 情況3:類 :: 實(shí)例方法名

4.1.2 方法引用使用前提

要求1:Lambda體只有一句語(yǔ)句,并且是通過(guò)調(diào)用一個(gè)對(duì)象的/類現(xiàn)有的方法來(lái)完成的

例如:System.out對(duì)象,調(diào)用println()方法來(lái)完成Lambda體

Math類,調(diào)用random()靜態(tài)方法來(lái)完成Lambda體

要求2:

針對(duì)情況1:函數(shù)式接口中的抽象方法a在被重寫(xiě)時(shí)使用了某一個(gè)對(duì)象的方法b。如果方法a的形參列表、返回值類型與方法b的形參列表、返回值類型都相同,則我們可以使用方法b實(shí)現(xiàn)對(duì)方法a的重寫(xiě)、替換。

針對(duì)情況2:函數(shù)式接口中的抽象方法a在被重寫(xiě)時(shí)使用了某一個(gè)類的靜態(tài)方法b如果方法a的形參列表、返回值類型與方法b的形參列表、返回值類型都相同,則我們可以使用方法b實(shí)現(xiàn)對(duì)方法a的重寫(xiě)、替換。

針對(duì)情況3:函數(shù)式接口中的抽象方法a在被重寫(xiě)時(shí)使用了某一個(gè)對(duì)象的方法b如果方法a的返回值類型與方法b的返回值類型相同,同時(shí)方法a的形參列表中有n個(gè)參數(shù),方法b的形參列表有n-1個(gè)參數(shù),且方法a的第1個(gè)參數(shù)作為方法b的調(diào)用者,且方法a的后n-1參數(shù)與方法b的n-1參數(shù)匹配(類型相同或滿足多態(tài)場(chǎng)景也可以)

例如:t->System.out.println(t)

() -> Math.random() 都是無(wú)參

4.1.3 舉例

public class MethodRefTest {

	// 情況一:對(duì)象 :: 實(shí)例方法
	//Consumer中的void accept(T t)
	//PrintStream中的void println(T t)
	@Test
	public void test1() {
		Consumer<String> con1 = str -> System.out.println(str);
		con1.accept("北京");

		System.out.println("*******************");
		PrintStream ps = System.out;
		Consumer<String> con2 = ps::println;
		con2.accept("beijing");
	}
	
	//Supplier中的T get()
	//Employee中的String getName()
	@Test
	public void test2() {
		Employee emp = new Employee(1001,"Tom",23,5600);

		Supplier<String> sup1 = () -> emp.getName();
		System.out.println(sup1.get());

		System.out.println("*******************");
		Supplier<String> sup2 = emp::getName;
		System.out.println(sup2.get());

	}

	// 情況二:類 :: 靜態(tài)方法
	//Comparator中的int compare(T t1,T t2)
	//Integer中的int compare(T t1,T t2)
	@Test
	public void test3() {
		Comparator<Integer> com1 = (t1,t2) -> Integer.compare(t1,t2);
		System.out.println(com1.compare(12,21));

		System.out.println("*******************");

		Comparator<Integer> com2 = Integer::compare;
		System.out.println(com2.compare(12,3));

	}
	
	//Function中的R apply(T t)
	//Math中的Long round(Double d)
	@Test
	public void test4() {
		Function<Double,Long> func = new Function<Double, Long>() {
			@Override
			public Long apply(Double d) {
				return Math.round(d);
			}
		};

		System.out.println("*******************");

		Function<Double,Long> func1 = d -> Math.round(d);
		System.out.println(func1.apply(12.3));

		System.out.println("*******************");

		Function<Double,Long> func2 = Math::round;
		System.out.println(func2.apply(12.6));
	}

	// 情況三:類 :: 實(shí)例方法  (有難度)
	// Comparator中的int comapre(T t1,T t2)
	// String中的int t1.compareTo(t2)
	@Test
	public void test5() {
		Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
		System.out.println(com1.compare("abc","abd"));

		System.out.println("*******************");

		Comparator<String> com2 = String :: compareTo;
		System.out.println(com2.compare("abd","abm"));
	}

	//BiPredicate中的boolean test(T t1, T t2);
	//String中的boolean t1.equals(t2)
	@Test
	public void test6() {
		BiPredicate<String,String> pre1 = (s1,s2) -> s1.equals(s2);
		System.out.println(pre1.test("abc","abc"));

		System.out.println("*******************");
		BiPredicate<String,String> pre2 = String :: equals;
		System.out.println(pre2.test("abc","abd"));
	}
	
	// Function中的R apply(T t)
	// Employee中的String getName();
	@Test
	public void test7() {
		Employee employee = new Employee(1001, "Jerry", 23, 6000);


		Function<Employee,String> func1 = e -> e.getName();
		System.out.println(func1.apply(employee));

		System.out.println("*******************");
		Function<Employee,String> func2 = Employee::getName;
		System.out.println(func2.apply(employee));
	}

}

4.2 構(gòu)造器引用

當(dāng)Lambda表達(dá)式是創(chuàng)建一個(gè)對(duì)象,并且滿足Lambda表達(dá)式形參,正好是給創(chuàng)建這個(gè)對(duì)象的構(gòu)造器的實(shí)參列表,就可以使用構(gòu)造器引用。

格式:類名::new

舉例:

public class ConstructorRefTest {
	//構(gòu)造器引用
    //Supplier中的T get()
    //Employee的空參構(gòu)造器:Employee()
    @Test
    public void test1(){

        Supplier<Employee> sup = new Supplier<Employee>() {
            @Override
            public Employee get() {
                return new Employee();
            }
        };
        System.out.println("*******************");

        Supplier<Employee>  sup1 = () -> new Employee();
        System.out.println(sup1.get());

        System.out.println("*******************");

        Supplier<Employee>  sup2 = Employee :: new;
        System.out.println(sup2.get());
    }

	//Function中的R apply(T t)
    @Test
    public void test2(){
        Function<Integer,Employee> func1 = id -> new Employee(id);
        Employee employee = func1.apply(1001);
        System.out.println(employee);

        System.out.println("*******************");

        Function<Integer,Employee> func2 = Employee :: new;
        Employee employee1 = func2.apply(1002);
        System.out.println(employee1);

    }

	//BiFunction中的R apply(T t,U u)
    @Test
    public void test3(){
        BiFunction<Integer,String,Employee> func1 = (id,name) -> new Employee(id,name);
        System.out.println(func1.apply(1001,"Tom"));

        System.out.println("*******************");

        BiFunction<Integer,String,Employee> func2 = Employee :: new;
        System.out.println(func2.apply(1002,"Tom"));

    }

}
public class Employee {

	private int id;
	private String name;
	private int age;
	private double salary;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public Employee() {
		System.out.println("Employee().....");
	}

	public Employee(int id) {
		this.id = id;
		System.out.println("Employee(int id).....");
	}

	public Employee(int id, String name) {
		this.id = id;
		this.name = name;
	}

	public Employee(int id, String name, int age, double salary) {

		this.id = id;
		this.name = name;
		this.age = age;
		this.salary = salary;
	}

	@Override
	public String toString() {
		return "Employee{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", salary=" + salary + '}';
	}

}

4.3 數(shù)組構(gòu)造引用

當(dāng)Lambda表達(dá)式是創(chuàng)建一個(gè)數(shù)組對(duì)象,并且滿足Lambda表達(dá)式形參,正好是給創(chuàng)建這個(gè)數(shù)組對(duì)象的長(zhǎng)度,就可以數(shù)組構(gòu)造引用。

格式:數(shù)組類型名::new

舉例:

//數(shù)組引用
//Function中的R apply(T t)
@Test
public void test4(){
    Function<Integer,String[]> func1 = length -> new String[length];
    String[] arr1 = func1.apply(5);
    System.out.println(Arrays.toString(arr1));

    System.out.println("*******************");

    Function<Integer,String[]> func2 = String[] :: new;
    String[] arr2 = func2.apply(10);
    System.out.println(Arrays.toString(arr2));

}

5. Java8新特性:強(qiáng)大的Stream API

5.1 說(shuō)明

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

  • Stream API ( java.util.stream) 把真正的函數(shù)式編程風(fēng)格引入到Java中。這是目前為止對(duì)Java類庫(kù)最好的補(bǔ)充,因?yàn)镾tream API可以極大提供Java程序員的生產(chǎn)力,讓程序員寫(xiě)出高效率、干凈、簡(jiǎn)潔的代碼。

  • Stream 是 Java8 中處理集合的關(guān)鍵抽象概念,它可以指定你希望對(duì)集合進(jìn)行的操作,可以執(zhí)行非常復(fù)雜的查找、過(guò)濾和映射數(shù)據(jù)等操作。 使用Stream API 對(duì)集合數(shù)據(jù)進(jìn)行操作,就類似于使用 SQL 執(zhí)行的數(shù)據(jù)庫(kù)查詢也可以使用 Stream API 來(lái)并行執(zhí)行操作。簡(jiǎn)言之,Stream API 提供了一種高效且易于使用的處理數(shù)據(jù)的方式。

5.2 為什么要使用Stream API

實(shí)際開(kāi)發(fā)中,項(xiàng)目中多數(shù)數(shù)據(jù)源都來(lái)自于MySQL、Oracle等。但現(xiàn)在數(shù)據(jù)源可以更多了,有MongDB,Radis等,而這些NoSQL的數(shù)據(jù)就需要Java層面去處理。

5.3 什么是Stream

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

Stream 和 Collection 集合的區(qū)別:Collection 是一種靜態(tài)的內(nèi)存數(shù)據(jù)結(jié)構(gòu),講的是數(shù)據(jù),而 Stream 是有關(guān)計(jì)算的,講的是計(jì)算。前者是主要面向內(nèi)存,存儲(chǔ)在內(nèi)存中,后者主要是面向 CPU,通過(guò) CPU 實(shí)現(xiàn)計(jì)算。

注意:

①Stream 自己不會(huì)存儲(chǔ)元素。

②Stream 不會(huì)改變?cè)磳?duì)象。相反,他們會(huì)返回一個(gè)持有結(jié)果的新Stream。

③Stream 操作是延遲執(zhí)行的。這意味著他們會(huì)等到需要結(jié)果的時(shí)候才執(zhí)行。即一旦執(zhí)行終止操作,就執(zhí)行中間操作鏈,并產(chǎn)生結(jié)果。

④ Stream一旦執(zhí)行了終止操作,就不能再調(diào)用其它中間操作或終止操作了。

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

1 - 創(chuàng)建 Stream 一個(gè)數(shù)據(jù)源(如:集合、數(shù)組),獲取一個(gè)流

2 - 中間操作 每次處理都會(huì)返回一個(gè)持有結(jié)果的新Stream,即中間操作的方法返回值仍然是Stream類型的對(duì)象。因此中間操作可以是個(gè)操作鏈,可對(duì)數(shù)據(jù)源的數(shù)據(jù)進(jìn)行n次處理,但是在終結(jié)操作前,并不會(huì)真正執(zhí)行。

3 - 終止操作(終端操作) 終止操作的方法返回值類型就不再是Stream了,因此一旦執(zhí)行終止操作,就結(jié)束整個(gè)Stream操作了。一旦執(zhí)行終止操作,就執(zhí)行中間操作鏈,最終產(chǎn)生結(jié)果并結(jié)束Stream。

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》?

5.4.1 創(chuàng)建Stream實(shí)例

方式一:通過(guò)集合

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

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

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

@Test
public void test01(){
    List<Integer> list = Arrays.asList(1,2,3,4,5);

    //JDK1.8中,Collection系列集合增加了方法
    Stream<Integer> stream = list.stream();
}

方式二:通過(guò)數(shù)組

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

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

  • public static IntStream stream(int[] array)

  • public static LongStream stream(long[] array)

  • public static DoubleStream stream(double[] array)

@Test
public void test02(){
    String[] arr = {"hello","world"};
    Stream<String> stream = Arrays.stream(arr); 
}

@Test
public void test03(){
    int[] arr = {1,2,3,4,5};
    IntStream stream = Arrays.stream(arr);
}

方式三:通過(guò)Stream的of()

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

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

@Test
public void test04(){
    Stream<Integer> stream = Stream.of(1,2,3,4,5);
    stream.forEach(System.out::println);
}

方式四:創(chuàng)建無(wú)限流(了解)

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

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

  • 生成 public static<T> Stream<T> generate(Supplier<T> s)

// 方式四:創(chuàng)建無(wú)限流
@Test
public void test05() {
	// 迭代
	// public static<T> Stream<T> iterate(final T seed, final
	// UnaryOperator<T> f)
	Stream<Integer> stream = Stream.iterate(0, x -> x + 2);
	stream.limit(10).forEach(System.out::println);

	// 生成
	// public static<T> Stream<T> generate(Supplier<T> s)
	Stream<Double> stream1 = Stream.generate(Math::random);
	stream1.limit(10).forEach(System.out::println);
}

5.4.2 一系列中間操作

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

1 - 篩選與切片

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

2 - 映射

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》3 - 排序

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》代碼舉例:

import org.junit.Test;

import java.util.Arrays;
import java.util.stream.Stream;

public class StreamMiddleOperate {
	@Test
    public void test01(){
        //1、創(chuàng)建Stream
        Stream<Integer> stream = Stream.of(1,2,3,4,5,6);

        //2、加工處理
        //過(guò)濾:filter(Predicate?p)
        //把里面的偶數(shù)拿出來(lái)
        /*
         * filter(Predicate?p)
         * Predicate是函數(shù)式接口,抽象方法:boolean test(T t)
         */
        stream = stream.filter(t -> t%2==0);

        //3、終結(jié)操作:例如:遍歷
        stream.forEach(System.out::println);
    }
    @Test
    public void test02(){
        Stream.of(1,2,3,4,5,6)
                .filter(t -> t%2==0)
                .forEach(System.out::println);
    }
    @Test
    public void test03(){
        Stream.of(1,2,3,4,5,6,2,2,3,3,4,4,5)
                .distinct()
                .forEach(System.out::println);
    }
    @Test
    public void test04(){
        Stream.of(1,2,3,4,5,6,2,2,3,3,4,4,5)
                .limit(3)
                .forEach(System.out::println);
    }
    @Test
    public void test05(){
        Stream.of(1,2,2,3,3,4,4,5,2,3,4,5,6,7)
                .distinct()  //(1,2,3,4,5,6,7)
                .filter(t -> t%2!=0) //(1,3,5,7)
                .limit(3)
                .forEach(System.out::println);
    }
    @Test
    public void test06(){
        Stream.of(1,2,3,4,5,6,2,2,3,3,4,4,5)
                .skip(5)
                .forEach(System.out::println);
    }
    @Test
    public void test07(){
        Stream.of(1,2,3,4,5,6,2,2,3,3,4,4,5)
                .skip(5)
                .distinct()
                .filter(t -> t%3==0)
                .forEach(System.out::println);
    }
    @Test
    public void test08(){
        long count = Stream.of(1,2,3,4,5,6,2,2,3,3,4,4,5)
                .distinct()
                .peek(System.out::println)  //Consumer接口的抽象方法  void accept(T t)
                .count();
        System.out.println("count="+count);
    }
    @Test
    public void test09(){
        //希望能夠找出前三個(gè)最大值,前三名最大的,不重復(fù)
        Stream.of(11,2,39,4,54,6,2,22,3,3,4,54,54)
                .distinct()
                .sorted((t1,t2) -> -Integer.compare(t1, t2))//Comparator接口  int compare(T t1, T t2)
                .limit(3)
                .forEach(System.out::println);
    }
    @Test
    public void test10(){
        Stream.of(1,2,3,4,5)
                .map(t -> t+=1)//Function<T,R>接口抽象方法 R apply(T t)
                .forEach(System.out::println);
    }
    @Test
    public void test11(){
        String[] arr = {"hello","world","java"};

        Arrays.stream(arr)
                .map(t->t.toUpperCase())
                .forEach(System.out::println);
    }
    @Test
    public void test12(){
        String[] arr = {"hello","world","java"};
        Arrays.stream(arr)
                .flatMap(t -> Stream.of(t.split("|")))//Function<T,R>接口抽象方法 R apply(T t)  現(xiàn)在的R是一個(gè)Stream
                .forEach(System.out::println);
    } 
}

5.4.3 終止操作

  • 終端操作會(huì)從流的流水線生成結(jié)果。其結(jié)果可以是任何不是流的值,例如:List、Integer,甚至是 void 。

  • 流進(jìn)行了終止操作后,不能再次使用。

1 - 匹配與查找

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

2 - 歸約

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》3 - 收集

Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

Collector 接口中方法的實(shí)現(xiàn)決定了如何對(duì)流執(zhí)行收集的操作(如收集到 List、Set、Map)。

另外, Collectors 實(shí)用類提供了很多靜態(tài)方法,可以方便地創(chuàng)建常見(jiàn)收集器實(shí)例,具體方法與實(shí)例如下表:

方法 返回類型 作用
toList Collector<T, ?, List<T>> 把流中元素收集到List
List<Employee> emps = list.stream().collect(Collectors.toList());
方法 返回類型 作用
toSet Collector<T, ?, Set<T>> 把流中元素收集到Set
Set<Employee> emps= list.stream().collect(Collectors.toSet());
方法 返回類型 作用
toCollection Collector<T, ?, C> 把流中元素收集到創(chuàng)建的集合
Collection<Employee> emps =
list.stream().collect(Collectors.toCollection(ArrayList::new));
方法 返回類型 作用
counting Collector<T, ?, Long> 計(jì)算流中元素的個(gè)數(shù)
long count = list.stream().collect(Collectors.counting());
方法 返回類型 作用
summingInt Collector<T, ?, Integer> 對(duì)流中元素的整數(shù)屬性求和
int total=list.stream().collect(Collectors.summingInt(Employee::getSalary));
方法 返回類型 作用
averagingInt Collector<T, ?, Double> 計(jì)算流中元素Integer屬性的平均值
double avg = list.stream().collect(Collectors.averagingInt(Employee::getSalary));
方法 返回類型 作用
summarizingInt Collector<T, ?, IntSummaryStatistics> 收集流中Integer屬性的統(tǒng)計(jì)值。如:平均值
int SummaryStatisticsiss=
list.stream().collect(Collectors.summarizingInt(Employee::getSalary));
方法 返回類型 作用
joining Collector<CharSequence, ?, String> 連接流中每個(gè)字符串
String str= list.stream().map(Employee::getName).collect(Collectors.joining());
方法 返回類型 作用
maxBy Collector<T, ?, Optional<T>> 根據(jù)比較器選擇最大值
Optional<Emp>max= 
list.stream().collect(Collectors.maxBy(comparingInt(Employee::getSalary)));
方法 返回類型 作用
minBy Collector<T, ?, Optional<T>> 根據(jù)比較器選擇最小值
Optional<Emp> min = 
list.stream().collect(Collectors.minBy(comparingInt(Employee::getSalary)));
方法 返回類型 作用
reducing Collector<T, ?, Optional<T>> 從一個(gè)作為累加器的初始值開(kāi)始,利用BinaryOperator與流中元素逐個(gè)結(jié)合,從而歸約成單個(gè)值
int total=
list.stream().collect(Collectors.reducing(0, Employee::getSalar, Integer::sum));
方法 返回類型 作用
collectingAndThen Collector<T,A,RR> 包裹另一個(gè)收集器,對(duì)其結(jié)果轉(zhuǎn)換函數(shù)
int how = 
list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), List::size));
方法 返回類型 作用
groupingBy Collector<T, ?, Map<K, List<T>>> 根據(jù)某屬性值對(duì)流分組,屬性為K,結(jié)果為V
Map<Emp.Status, List<Emp>> map= 
list.stream().collect(Collectors.groupingBy(Employee::getStatus));
方法 返回類型 作用
partitioningBy Collector<T, ?, Map<Boolean, List<T>>> 根據(jù)true或false進(jìn)行分區(qū)
Map<Boolean,List<Emp>> vd = 
list.stream().collect(Collectors.partitioningBy(Employee::getManage));

舉例

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.junit.Test;

public class StreamEndding {
    @Test
    public void test01(){
        Stream.of(1,2,3,4,5)
                .forEach(System.out::println);
    }
    @Test
    public void test02(){
        long count = Stream.of(1,2,3,4,5)
                .count();
        System.out.println("count = " + count);
    }
    @Test
    public void test03(){
        boolean result = Stream.of(1,3,5,7,9)
                .allMatch(t -> t%2!=0);
        System.out.println(result);
    }
	@Test
    public void test04(){
        boolean result = Stream.of(1,3,5,7,9)
                .anyMatch(t -> t%2==0);
        System.out.println(result);
    }
	@Test
    public void test05(){
        Optional<Integer> opt = Stream.of(1,3,5,7,9).findFirst();
        System.out.println(opt);
    }
	@Test
    public void test06(){
        Optional<Integer> opt = Stream.of(1,2,3,4,5,7,9)
                .filter(t -> t%3==0)
                .findFirst();
        System.out.println(opt);
    }
	@Test
    public void test07(){
        Optional<Integer> opt = Stream.of(1,2,4,5,7,8)
                .filter(t -> t%3==0)
                .findFirst();
        System.out.println(opt);
    }
    @Test
    public void test08(){
        Optional<Integer> max = Stream.of(1,2,4,5,7,8)
                .max((t1,t2) -> Integer.compare(t1, t2));
        System.out.println(max);
    }
    @Test
    public void test09(){
        Integer reduce = Stream.of(1,2,4,5,7,8)
                .reduce(0, (t1,t2) -> t1+t2);//BinaryOperator接口   T apply(T t1, T t2)
        System.out.println(reduce);
    }
    @Test
    public void test10(){
        Optional<Integer> max = Stream.of(1,2,4,5,7,8)
                .reduce((t1,t2) -> t1>t2?t1:t2);//BinaryOperator接口   T apply(T t1, T t2)
        System.out.println(max);
    }
    @Test
    public void test11(){
        List<Integer> list = Stream.of(1,2,4,5,7,8)
                .filter(t -> t%2==0)
                .collect(Collectors.toList());

        System.out.println(list);
    }   
}

5.5 Java9新增API

新增1:Stream實(shí)例化方法

ofNullable()的使用:

Java 8 中 Stream 不能完全為null,否則會(huì)報(bào)空指針異常。而 Java 9 中的 ofNullable 方法允許我們創(chuàng)建一個(gè)單元素 Stream,可以包含一個(gè)非空元素,也可以創(chuàng)建一個(gè)空 Stream。

//報(bào)NullPointerException
//Stream<Object> stream1 = Stream.of(null);
//System.out.println(stream1.count());

//不報(bào)異常,允許通過(guò)
Stream<String> stringStream = Stream.of("AA", "BB", null);
System.out.println(stringStream.count());//3

//不報(bào)異常,允許通過(guò)
List<String> list = new ArrayList<>();
list.add("AA");
list.add(null);
System.out.println(list.stream().count());//2
//ofNullable():允許值為null
Stream<Object> stream1 = Stream.ofNullable(null);
System.out.println(stream1.count());//0

Stream<String> stream = Stream.ofNullable("hello world");
System.out.println(stream.count());//1

?iterator()重載的使用:

//原來(lái)的控制終止方式:
Stream.iterate(1,i -> i + 1).limit(10).forEach(System.out::println);

//現(xiàn)在的終止方式:
Stream.iterate(1,i -> i < 100,i -> i + 1).forEach(System.out::println);

5.6 練習(xí)

現(xiàn)在有兩個(gè) ArrayList 集合存儲(chǔ)隊(duì)伍當(dāng)中的多個(gè)成員姓名,要求使用傳統(tǒng)的for循環(huán)(或增強(qiáng)for循環(huán))依次進(jìn)行以 下若干操作步驟:

  1. 第一個(gè)隊(duì)伍只要名字為3個(gè)字的成員姓名;存儲(chǔ)到一個(gè)新集合中。

  2. 第一個(gè)隊(duì)伍篩選之后只要前3個(gè)人;存儲(chǔ)到一個(gè)新集合中。

  3. 第二個(gè)隊(duì)伍只要姓張的成員姓名;存儲(chǔ)到一個(gè)新集合中。

  4. 第二個(gè)隊(duì)伍篩選之后不要前2個(gè)人;存儲(chǔ)到一個(gè)新集合中。

  5. 將兩個(gè)隊(duì)伍合并為一個(gè)隊(duì)伍;存儲(chǔ)到一個(gè)新集合中。

  6. 根據(jù)姓名創(chuàng)建 Person 對(duì)象;存儲(chǔ)到一個(gè)新集合中。

  7. 打印整個(gè)隊(duì)伍的Person對(duì)象信息。

Person 類的代碼為:

public?class?Person?{
????private?String?name;
????public?Person()?{}
????public?Person(String?name)?{
????????this.name?=?name;
????}????
????public?String?getName()?{
????????return?name;
????}
????public?void?setName(String?name)?{
????????this.name?=?name;
????}
????@Override
????public?String?toString()?{
????????return?"Person{name='"?+?name?+?"'}";
????}
}

?兩個(gè)隊(duì)伍(集合)的代碼如下:

public?static?void?main(String[]?args)?{
???????//第一支隊(duì)伍
????????ArrayList<String>?one?=?new?ArrayList<>();
????????one.add("迪麗熱巴");
????????one.add("宋遠(yuǎn)橋");
????????one.add("蘇星河");
????????one.add("石破天");
????????one.add("石中玉");
????????one.add("老子");
????????one.add("莊子");
????????one.add("洪七公");
????????//第二支隊(duì)伍
????????ArrayList<String>?two?=?new?ArrayList<>();
????????two.add("古力娜扎");
????????two.add("張無(wú)忌");
????????two.add("趙麗穎");
????????two.add("張三豐");
????????two.add("尼古拉斯趙四");
????????two.add("張?zhí)鞇?ài)");
????????two.add("張二狗");
    
		//?....編寫(xiě)代碼完成題目要求?
????}

參考答案:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-421592.html

public?static?void?main(String[]?args)?{
???????//第一支隊(duì)伍
????????ArrayList<String>?one?=?new?ArrayList<>();
????????one.add("迪麗熱巴");
????????one.add("宋遠(yuǎn)橋");
????????one.add("蘇星河");
????????one.add("石破天");
????????one.add("石中玉");
????????one.add("老子");
????????one.add("莊子");
????????one.add("洪七公");
    
????????//第二支隊(duì)伍
????????ArrayList<String>?two?=?new?ArrayList<>();
????????two.add("古力娜扎");
????????two.add("張無(wú)忌");
????????two.add("趙麗穎");
????????two.add("張三豐");
????????two.add("尼古拉斯趙四");
????????two.add("張?zhí)鞇?ài)");
????????two.add("張二狗");
????????
		//?第一個(gè)隊(duì)伍只要名字為3個(gè)字的成員姓名;
????????//?第一個(gè)隊(duì)伍篩選之后只要前3個(gè)人;
????????Stream<String>?streamOne?=?one.stream().filter(s?‐>?s.length()?==?3).limit(3);
    
????????//?第二個(gè)隊(duì)伍只要姓張的成員姓名;
????????//?第二個(gè)隊(duì)伍篩選之后不要前2個(gè)人;
????????Stream<String>?streamTwo?=?two.stream().filter(s?‐>?s.startsWith("張")).skip(2);
    
????????//?將兩個(gè)隊(duì)伍合并為一個(gè)隊(duì)伍;
????????//?根據(jù)姓名創(chuàng)建Person對(duì)象;
????????//?打印整個(gè)隊(duì)伍的Person對(duì)象信息。
????????Stream.concat(streamOne,?streamTwo).map(Person::new).forEach(System.out::println);
????????
}

到了這里,關(guān)于Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 遷移學(xué)習(xí)、微調(diào)、計(jì)算機(jī)視覺(jué)理論(第十一次組會(huì)ppt)
  • 編譯技術(shù)-語(yǔ)法理論

    編譯技術(shù)-語(yǔ)法理論

    1.1 語(yǔ)法分析的目的 ? 語(yǔ)法分析是在進(jìn)行完詞法分析后進(jìn)行的步驟,詞法分析會(huì)將一個(gè)個(gè)的字母拆解成不同的符號(hào),這些符號(hào)會(huì)被組成一個(gè)線性的數(shù)組交給語(yǔ)法分析部分,語(yǔ)法分析不會(huì)會(huì)將這個(gè)線性的數(shù)組重新組織成一個(gè)語(yǔ)法樹(shù),交給后面的語(yǔ)義分析部分。 ? 至于為什么要

    2023年04月09日
    瀏覽(18)
  • Rust vs Go:常用語(yǔ)法對(duì)比(十一)

    Rust vs Go:常用語(yǔ)法對(duì)比(十一)

    題目來(lái)自 Rust Vs Go: Which Language Is Better For Developing High-Performance Applications? [1] 202. Sum of squares Calculate the sum of squares s of data, an array of floating point values. 計(jì)算平方和 +1.094200e+000 32.25 205. Get an environment variable Read an environment variable with the name \\\"FOO\\\" and assign it to the string variable foo. If i

    2024年02月15日
    瀏覽(19)
  • 【微信小程序】-- WXML 模板語(yǔ)法 - 條件渲染 -- wx:if & hidden (十一)

    【微信小程序】-- WXML 模板語(yǔ)法 - 條件渲染 -- wx:if & hidden (十一)

    ?? 所屬專欄:【微信小程序開(kāi)發(fā)教程】 ?? 作??者:我是夜闌的狗?? ?? 個(gè)人簡(jiǎn)介:一個(gè)正在努力學(xué)技術(shù)的CV工程師,專注基礎(chǔ)和實(shí)戰(zhàn)分享 ,歡迎咨詢! ?? 歡迎大家:這里是CSDN,我總結(jié)知識(shí)的地方,喜歡的話請(qǐng)三連,有問(wèn)題請(qǐng)私信 ?? ?? ?? ??大家好,又見(jiàn)面了,

    2024年02月05日
    瀏覽(38)
  • 第四章--Redis基礎(chǔ)知識(shí)和面試題

    第四章--Redis基礎(chǔ)知識(shí)和面試題

    Redis 是一個(gè)基于內(nèi)存的k-v結(jié)構(gòu)數(shù)據(jù)庫(kù) 基于內(nèi)存存儲(chǔ),讀寫(xiě)性能高 適合存儲(chǔ)熱點(diǎn)數(shù)據(jù)(熱點(diǎn)商品, 資訊, 新聞) 企業(yè)應(yīng)用廣泛 Redis入門 簡(jiǎn)介: 應(yīng)用場(chǎng)景 ?緩存 任務(wù)隊(duì)列 消息隊(duì)列 分布式鎖 數(shù)據(jù)類型 常用命令 redis常用命令鏈接 redis.net.cn java中操作redis 介紹 :::info redis啟動(dòng)默認(rèn)有16個(gè)

    2024年02月07日
    瀏覽(24)
  • Java jdk8生成隨機(jī)數(shù)

    目錄 Jdk8生成隨機(jī)數(shù) Jdk8以前 在Java 8中,可以使用ThreadLocalRandom類來(lái)生成隨機(jī)數(shù)。相比于早期的Random類,ThreadLocalRandom類可以更好地支持多線程應(yīng)用,性能也更優(yōu)。下面是使用ThreadLocalRandom類生成隨機(jī)數(shù)的幾種方法: 生成一個(gè)0到n之間的隨機(jī)整數(shù)(不包含n): 生成一個(gè)范圍在

    2024年02月12日
    瀏覽(13)
  • 【Java】JDK8 jvm參數(shù)配置及說(shuō)明

    -Xms 或 -XX:InitialHeapSize=n 設(shè)置堆的初始值 指令1:-Xms2g 指令2:-XX:InitialHeapSize=2048m -Xmx 或 -XX:MaxHeapSize=n 設(shè)置堆區(qū)最大值 指令1: -Xmx2g 指令2: -XX:MaxHeapSize=2048m -XX:NewSize=n 設(shè)置年輕代大小 -Xss 或 -XX:ThreadStackSize=n 每個(gè)線程堆棧最大值 指令1:-Xss256k 指令2:-XX:ThreadStackSize=256k 注意:

    2024年02月03日
    瀏覽(50)
  • 前端 | ( 十一)CSS3簡(jiǎn)介及基本語(yǔ)法(上) | 尚硅谷前端html+css零基礎(chǔ)教程2023最新

    前端 | ( 十一)CSS3簡(jiǎn)介及基本語(yǔ)法(上) | 尚硅谷前端html+css零基礎(chǔ)教程2023最新

    學(xué)習(xí)來(lái)源 :尚硅谷前端html+css零基礎(chǔ)教程,2023最新前端開(kāi)發(fā)html5+css3視頻 系列筆記 : 【HTML4】(一)前端簡(jiǎn)介 【HTML4】(二)各種各樣的常用標(biāo)簽 【HTML4】(三)表單及HTML4收尾 【CSS2】(四)CSS基礎(chǔ)及CSS選擇器 【CSS2】(五)CSS三大特性及常用屬性 【CSS2】(六)CSS盒子模型

    2024年02月16日
    瀏覽(58)
  • java jdk8和jdk17同時(shí)存在【環(huán)境配置】

    java jdk8和jdk17同時(shí)存在【環(huán)境配置】

    jdk8:https://www.oracle.com/cn/java/technologies/javase/javase8u211-later-archive-downloads.html jdk17:https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html PS:jdk8在下載結(jié)束,安裝的時(shí)候,需要有兩個(gè)文件分別是jre和jdk JRE: 是Java Runtime Environment,是java程序的運(yùn)行環(huán)境。既然是運(yùn)行,當(dāng)然要包含

    2024年02月07日
    瀏覽(32)
  • JDK8 和 JDK11 Java 兩個(gè)主要版本的比較

    Java 是一門廣泛應(yīng)用于企業(yè)級(jí)應(yīng)用和跨平臺(tái)開(kāi)發(fā)的編程語(yǔ)言。隨著時(shí)間的推移,Java 不斷演變和發(fā)展,版本之間有著許多新的功能和改進(jìn)。本篇博客將重點(diǎn)關(guān)注 JDK 8 和 JDK 11 之間的區(qū)別,分析它們的新特性、性能改進(jìn)和其他方面的差異。 一、性能改進(jìn): JDK 11 對(duì)性能進(jìn)行了優(yōu)化

    2024年02月09日
    瀏覽(25)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包