Kai Chen
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # 六角鼠年鐵人賽 Week 16 - Spring Boot - 番外篇 Java 8 Lambda Tutorial ==大家好,我是 "為了拿到金角獎盃而努力著" 的文毅青年 - Kai== ## 劇中佳句 一代宗師 :::info 念念不忘,必有回響 ::: ## 主題 這週與下週都會各自寫個番外篇特別來介紹 Java 8 的 Lambda expression 和 Stream 的學習心得分享。 為什麼要特別提到這兩個 feature 呢? 因為對 Java 來說,從 7 -> 8 可以說是 Java 史上最大幅度的改變! 而當中最大的改變莫屬這兩個 feature 不可。 到底他們有多大的能耐可以造就這歷史級別的差異,就在文中慢慢來介紹了~ :::info **小知識分享** - Java 8 -> 9 也是有不少的內容改變和新 feature 加入,但考慮到 **歷史事件**( Oracle 收購昇陽、Java 開始收費)、**市場考量**(OpenJDK 的出現) 等因素,7 -> 8 的幅度切切實實的影響了所有的 Java 程式設計師。 ::: 時至今日,仍有不少金融企業的內部系統採用穩定的 Java 7;新一點的科技公司會升級使用到 Java 8;部分新創公司則開始嘗試導入 Java 11 的版本。 而為什麼大部分的 Java 系統還在採用 7 或 8 這種老舊的版本呢? 這是因為在眾多的 Java Plugin 使用上,大部分的套件都還是為 7 或 8 版本量身打造(因為這兩版本使用率最高),這些套件也沒有因為 Java 版本升級而去更新,部分會在 Java 版本跳升到使用 9 (甚至是 up 版本)時會有許多錯誤跑出,諸如 **Mavan**, **Gradle** 這類時常更新的套件也受到版本影響。 在企業管理的考量下,自然不會考慮到做升級的打算,畢竟面對無法預期的錯誤與可能造成的損失來看,這個投資性價比十分的低,因此大多公司若非必要是不會進行系統升級的。 (很多都是另起爐灶最快) 因此對於剛投入職場的 Java 工程師們,如果你是學習非常新穎的版本 (例如9, 10, 11, 12, 13, 14...),可能需要重新學習並去習慣較不方便的 7 或 8 的版本了。 > Java 7 在 2015年 4月 發出停止更新版本公告 > Java 8 在 2019年 1月 發出停止更新版本公告 ## Lambda 表示式 英文全名為 **Lambda Expression**,講到 Lambda 表示式,就必須連同 **Functional Interfaces** 和 **匿名類別**一起講,各位看官才會有感覺,因為透過 Lambda 表示式,將會大大改善使用 Functional Interfaces 和 匿名類別的方式。 :::info ### Functional Interfaces 並不是 Java 8 的新 feature,而是由 Interface class 衍生的一種新型態的 interface,強調快速使用為導向,是為了 Lambda 表示式而被強化的 interface,使用 Annotation @FunctionalInterface 進行 Class 的標註,其設計上的限制為該 Interface Class **僅能設計持有一支 abstract method** 例如: ```java= @FunctionalInterface public class testObject{ public void doTest(); // 若增加以下程式碼則會跳出錯誤: Unexpeted @FunctionalInterface Annotation //public void doTest2(); } ``` > Java 8 版本可以在 interface class 中設計實作方法,設計上的限制為必須使用 **default** 或是 **static** 的 method 宣告 > 例如: > ```java= > @FunctionalInterface > public class testObject{ > public void doTest(); > > // 一般類別成員方法 > public default void doCheck(){ > System.out.println("Checked!"); > } > > // 靜態類別方法 > public static void doCheck2(){ > System.out.println("Checked2!"); > } > } > ``` 若一個 interface 繼承一個 functional interface 時的狀況: - 在**不增加** abstract method 的情況下會在 Coding 時,**被視為 functional interface** - 在**增加 default** 或是 **static** 等方法情況下,**仍然被視為 functional interface** - 在**增加** abstract method 的情況下,會**不再被視為 functional interface**,後續無法使用 Lambda 表示式使用該 interface,必須遵照原本 interface 的使用方式。 ::: :::info ### 匿名類別 用來滿足系統實作時,面臨一次性修改且不更動原 Class 內容、透過繼承原類別或實作某些 Interface 的類別後進行修改並建成 Inner Class 存於該使用的 Class 中,並且這些 Inner Class 不需要被引用,我們就會將其設計成匿名內部類別,以方便我們繼續開發系統,避免過多一次性使用的類別而造成整體檔案架構的凌亂。 舉例大家常見的 String 為例子: ```java= Object s1 = new Object(){ @Override public String toString(){ return "I Override and update the content just in this String class."; } }; System.out.println("This is S1: " + s1.toString()); Object s2 = "check toString method."; System.out.println("This is S2: " + s2.toString()); ``` ``` Execute Result: This is S1: I Override and update the content just in this String class. This is S2: check toString method. ``` 從上述例子中大家可以清楚發現,Kai 因為需求關係,必須要修正 s1 物件的 toString() 這個方法,因此我直接在建立物件的同時去 Override 這個方法的內容,這就是一種典型的匿名內部類別,JVM 會在 Compile 該 Class 的同時在裡面建立一個新的 Inner Class 並繼承 Object 物件,然後將設計師寫的 Override 方法給放入其中。 這樣的修改僅會是一次性、專屬性的存在該 Class 當中,可以從 s1 與 s2 兩個物件最後都是呼叫 toString() 的差異看出端倪。 ::: ## 標準寫法 ```java= // 無參數 無回傳 多行 () -> { System.out.println("first line."); System.out.println("second line."); } // 無參數 無回傳 單行 () -> System.out.println("first line."); //有參數 有回傳 多行 (Integer i1,Integer i2) -> { i1 = i1 * 2; i2 = i2 * 3; return i1 + i2; } // 有參數 有回傳 單行 (Integer i1,Integer i2) -> i1 + i2; // 單參數 有回傳 多行 Integer i1 -> { i1 = Math.abs(i1); return i1 * 3; } // 單參數 有回傳 單行 Integer i1 -> Math.abs(i1) * 3; ``` ## 有無回傳值? 特別拿出來強調的一個標題,Lambda 表示式是用來方便開發匿名內部類別用的設計方式,不是用來寫完整新的 function 的東西! **所以用作參考原型的方法有無回傳,在 Lambda 表示式中會保持一樣的格式!!** **所以用作參考原型的方法有無回傳,在 Lambda 表示式中會保持一樣的格式!!** **所以用作參考原型的方法有無回傳,在 Lambda 表示式中會保持一樣的格式!!** 很重要,強調三遍! **Lambda 表示式可以改變的是內部程序,無法改變傳入、傳出的參數、方法的宣告和名稱** **Lambda 表示式可以改變的是內部程序,無法改變傳入、傳出的參數、方法的宣告和名稱** **Lambda 表示式可以改變的是內部程序,無法改變傳入、傳出的參數、方法的宣告和名稱** 再強調三遍! ## 優缺點?! 有好就有壞,而一個東西不論好壞,只要能夠使用在適當的地方,那就成功了一半! 在學習 Lambda 表示式的同時,我們必須了解這種設計方式所帶來的好與壞,才能將其妥善的運用在系統開發中 - 優點: - 大幅減少程式行數 - 增加程式閱讀性 - 增加運行效率 > 一般匿名內部類別,JVM compile 後會在檔案中產生一組 class 檔,但 Lambda 表示式則不會產出新檔案 - 缺點: - 需要了解其使用的 interface - 偵錯時的中斷點不好釘標 ## 常見的 Functional Interfaces 為了順應 Lambda 表示式的到來,許多我們以往常見的 interface 也已經在 Java 8 被調整為 Functional Interface 型態了。 ### Runnable 參數: Null 回傳: void ```java= Runnable r = () -> {System.out.println("Runnable with Lambda Expression");}; ``` ### Predicate 參數: T 回傳: Boolean ```java= Predicate<String> p = string -> string.length > 3; ``` ### Consumer 參數: T 回傳: void ```java= Consumner<String> c = string -> System.out.println(string); ``` ### Function 參數: T 回傳: R ```java= Function<String,Integer> f = string -> string.length; ``` ### Supplier 參數: Null 回傳: T ```java= Supplier<List<String>> s = () -> new ArrayList<String>(); ``` ### UnaryOperator 參數: T 回傳: T ```java= UnaryOperator<Integer> uo = (num) -> num + 1 ; ``` ### BinaryOperator 參數: (T,T) 回傳: T ```java= BinaryOperator<Interger> bo = (num1 , num2) -> num1 + num2; ``` ## Functional Interface 實例分享 ```java= package kai.com.lambda; public class MathMainTest { public static void main(String []args) { MathProcess mp = i1 -> Math.abs(i1) * 10; System.out.println("mp Result: " + mp.doOperator(10)); MathProcess2 mp2_add = (i1, i2) -> i1 + i2; MathProcess2 mp2_subtract = (i1, i2) -> i1 - i2; MathProcess2 mp2_multiply = (i1, i2) -> i1 * i2; MathProcess2 mp2_divided = (i1, i2) -> i1 / i2; MathProcess3 mp3 = (i1, i2, mp2) -> mp2.doOperator(i1, i2); System.out.println("Add Way: " + mp3.getResult(10, 5, mp2_add)); System.out.println("subtract Way: " + mp3.getResult(10, 5, mp2_subtract)); System.out.println("multiply Way: " + mp3.getResult(10, 5, mp2_multiply)); System.out.println("divided Way: " + mp3.getResult(10, 5, mp2_divided)); } } interface MathProcess { public Integer doOperator(int i); } interface MathProcess2 { public Integer doOperator(int i, int i2); } interface MathProcess3 { public Integer getResult(int i1 , int i2, MathProcess2 mp2); } ``` Kai 這邊寫了三個 interface 都放在 MathMainTest 底下,並在第一段,單純展示 Lambda 的應用,以往需要複雜再定義的匿名內部類別寫法,只需要透過 Lambda 短短一行即可實現目的。 ```java= MathProcess mp = i1 -> Math.abs(i1) * 10; System.out.println("mp Result: " + mp.doOperator(10)); ``` 再來是第二部分,Kai 透過兩個 interface 去組件出多種內部類別方法的可能性。 使用 mp2 interface 專門做出不同變化的程序方法,再將其透過 mp3 interface 轉變為統一呼叫使用的模組。 這種作業方式將會大大增強程式之間的彈性,mp2 可因應不同狀況實作不同程序給不同的 Class,而後,mp3 僅需加入包含有 mp2 的 class 與其要求的參數,即可充分運用個別 mp2 method 物件。 ```java= MathProcess2 mp2_add = (i1, i2) -> i1 + i2; MathProcess2 mp2_subtract = (i1, i2) -> i1 - i2; MathProcess2 mp2_multiply = (i1, i2) -> i1 * i2; MathProcess2 mp2_divided = (i1, i2) -> i1 / i2; MathProcess3 mp3 = (i1, i2, mp2) -> mp2.doOperator(i1, i2); System.out.println("Add Way: " + mp3.getResult(10, 5, mp2_add)); System.out.println("subtract Way: " + mp3.getResult(10, 5, mp2_subtract)); System.out.println("multiply Way: " + mp3.getResult(10, 5, mp2_multiply)); System.out.println("divided Way: " + mp3.getResult(10, 5, mp2_divided)); ``` ## Collection 實例分享 ```java= package kai.com.lambda; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class CollectionTest { public static void main(String [] args){ Map<String,String> map = new HashMap<>(); map.put("1","first"); map.put("2","second"); map.put("3","third"); map.forEach((k, v) -> System.out.println("Map get: " + k + ":" + v)); List<String> list = new ArrayList<>(); list.add("first"); list.add("second"); list.add("third"); list.forEach((k) -> System.out.println("List get: " + k)); } } ``` Collection 是非常非常使用的類別,舉凡 List, Set, Map 都包含在內,而在 Java 8 版本中,更特別增加了 - MAP: ```java= public void forEach(java.util.function.BiConsumer<? super K, ? super V> action) ``` - LIST: ```java= public void forEach(java.util.function.Consumer<? super T> action) ``` 等方法可以讓開發者進行 Lambda 表示式的覆寫,讓其使用在 for loop 中的應用更加方便。 ## 結語 :::danger 其餘還有很多 Lambda 的應用,Kai 這邊單純做介紹 Lambda 和其部分應用即可,後續還有一篇會特別來介紹一下 Stream,這個也是跟 Lambda 的應用非常相關的 feature。 [六角鼠年鐵人賽 Week 17 - Spring Boot - 番外篇 Java 8 Stream Tutorial](/l4MvMeuATGWcEzhGTDrGRQ) ::: 首頁 [Kai 個人技術 Hackmd](/2G-RoB0QTrKzkftH2uLueA) ###### tags: `Spring Boot`,`w3HexSchool`

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully