国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Upgrading to Java 8——第一章 Lambda表達式

2019-11-14 22:59:38
字體:
來源:轉載
供稿:網友
Upgrading to java 8——第一章 Lambda表達式

第一章 Lambda表達式

  Lamada 表達式是Java SE 8中最重要的新特性,長期以來被認為是在Java中缺失的特性,它的出現使整個java 語言變得完整。至少到目前,在這節中你將學習到什么是lambda,為什么他是出色的一部分。同時也會介紹一些新的技術例如單一抽象方法和函數式接口。

  為什么是lambda 表達式。

  就像閉包一樣, Lambda表達會使一些結構變得精簡和良好的可讀性,特別是在有處理內部類的時候。下面的例子是用內部類實現的代碼塊:

    Runnable runnable = new Runnable() {   

      @Override

      public void run() {    

        System.out.

      }    

    }

   其實,這些代碼可以用Lambda表達式替換成如下簡短的代碼:

     Runnable runnable = () -> System.out.println("Running...")

  換句話說, 如果你需要傳遞一個 runnable 接口給java.util.concurrent.Executor類,需要

    executor.execute(new Runnable() {

     @Override

      public void run() {

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

       }

     });

  但你可以用Lambda表達式實現同樣的效果,用下面的代碼;

    executor.execute(() -> System.out.println("Running..."));

  精短,優雅,干凈,更富有表達性。

  修改接口。

  在深入研究lambda之前,先介紹一下在java 8 中接口里可以包含defalut 和 static 方法。這部分解釋static和defalut 方法是什么,  為什么這里需要大幅度的修改使lambda 融入到java 核心庫中。

  默認方法

  將功能添加到接口是擴展接口一個安全的方式。不過,你最終會得到兩個功能相似的接口。如果你只需要繼承一個兩個接口還是可以接受的,  但如果需要添加新特性到成百的接口中,這就變成很嚴重的問題。

  這正是Java設計者們面對的問題,他們試圖添加lambda 到java8 中去支持在集合框架中數十個接口。這些接口需要添加新的方法去支持Lambda,但是擴展所有的接口只會產出一倍的接口,其中一些接口可能會冠以List2或ExtendeSet這些丑陋的名字。

  反而,他們通過添加default方法解決了這個問題。 默認方法是在接口中已經實現好的方法。一個接口實現類不用實現默認方法,這就意味著你 添加新的方法在接口中同時沒有打破向后兼容性問題。

  在接口中定義默認方法,只需要在方法簽名前加上“default”關鍵字即可。除此之外,添加大括號并在其中添加代碼。

  在以后能學到,在java8中很多接口都有默認方法。

  當你實現帶有默認方法的接口時,你有這些選擇:    忽略默認方法,直接繼承他們就生效。    重新聲明默認方法,要改成抽象方法。    重載默認方法。

  記住一點,java支持默認方法主要是為了向后兼容性。你絕不應該寫程序不用類。

  靜態方法。

  一個靜態方法供類的所有實例共享,在java8以后,你可以在接口中使用靜態方法 這樣與接口相關聯的所有靜態方法可以用接口,而不是一個幫助類.

  靜態方法的簽名跟默認方法的簽名很像,替代default關鍵字,使用static關鍵字,static在接口中默認是public的。

  靜態方法在接口中很少見,在java.util package包中將近30個接口,只有兩個有靜態方法。

  函數式接口

    除了默認方法和靜態方法,還有一個先決條件在學lambda之前:函數式接口。函數式接口只有一個抽象方法并且沒有重寫Object類中的方法,也被稱作單一抽象方法(SAM),

  java.lang.Runnable就是一個函數式接口,它只有一個抽象方法 run(),函數式接口可以有默認方法和靜態方法,復寫了Object類中的public的方法也算是函數式接口。

public interface Calculator {    double calculate(int a, int b);        public default int subtract(int a, int b) {        return a - b;    }    public default int add(int a, int b) {        return a * b;    }        @Override    public String toString();}

  在Java核心庫中常見的函數式接口有:java.lang.Runnable,java.lang.AutoCloseable,java.lang.Comparable,java.util.Comparator.此外,在java.util.function也有很多。

  函數式接口可以用注解@FunctionalInterface標注。

  為什么函數式接口這么重要?你可以使用函數式接口替代匿名內部類。如果不是,則不能這么用。

  lambda 表達式語法

  在上面的例子中calculate方法可以看作最基本的 lambda表達式語法。這個方法允許你定義任何的數學計算,使用兩個整形參數返回一個double類型。下面有兩個例子。

Calculator addition = (int a, int b) -> (a + b);System.out.println(addition.calculate(5, 20)); // prints 25.0Calculator division = (int a, int b) -> (double) a / b;System.out.println(division.calculate(5, 2)); // prints 2.5

Lambda表達式就是這么優雅,要是沒有它你該多寫多少代碼?

Lambda表達式的標準定義有兩種:

(parameter list) -> expression

(parameter list) -> {     statements}參數的類型跟接口中抽象方法的參數是一致的。不過,參數類型是可選的。換句話說,下面的方法是有效的。Calculator addition = (int a, int b) -> (a + b);Calculator addition = (a, b) -> (a + b);總結一下,Lambda表達式就是函數是接口實現的快捷方式,它相當于函數式接口實現的實例,因為在方法中可以使用Object作為參數,所以把Lambda表達式作為方法的參數也是可能的。Java中預定義的函數式接口java.util.function是java 8 中一個新包,里面包含了超過40個預定義函數式接口方便你去書寫 Lambda 表達式風格的代碼。下面是一些常用的接口。
函數式接口描述
Function傳遞一個參數返回一個結果。這個結果的類型可以與參數的類型不相同。
BiFunction傳遞兩個參數返回一個結果。這個結果的類型可以與任一參數的類型不相同。
UnaryOperator代表一個操作符的操作,它的返回結果類型與操作符的類型一樣。實際上它可以被看作是Function 它的返回結果跟參數一樣,它是Function 的子接口。
BiOperator代表兩個操作符的操作,它的返回結果類型必須與操作符相同。
Predicate傳遞一個參數,基于參數的值返回boolean值。
Supplier代表一個供應者的結果。
Consumer傳遞一個參數但沒有返回值。
Function, BiFunction and Other VariantsFunction接口通常用來創建一個參數的函數并返回一個結果。它是參數化的類型,定義如下:public interface Function<T, R>T是參數類型,R是返回的結果類型。Function只有一個抽象方法,apply,它的簽名如下:R apply(T argument)這個方法需要重寫當使用Function的時候,下面的例子定義了一個Function用來實現英米與公里的轉換。Function傳遞一個Integer類型作為參數,并返回Double類型。

public class FunctionDemo1 { public static void main(String[] args) { Function<Integer, Double> milesToKms = (input) -> 1.6 * input; int miles = 3; double kms = milesToKms.apply(miles); System.out.printf("%d miles = %3.2f kilometers/n", miles, kms); }

}

執行此類,在控制臺輸出:3 miles = 4.80 kilometersBiFunction是Function的一種變體,它傳遞兩個參數并返回一個結果,下面的例子創建一個Function 根據給定的長和寬計算面積,需要調用apply方法實現。
import java.util.function.BiFunction;public class BiFunctionDemo1 { public static void main(String[] args) { BiFunction<Float, Float, Float> area = (width, length) -> width * length; float width = 7.0F; float length = 10.0F; float result = area.apply(width, length); System.out.println(result); }}
控制臺輸出:70.0
除了BiFunction,還有一系列的Function變體,例如,IntFunction 只能傳遞int類型的參數。LongFunction and DoubleFunction 與IntFunction用法類似,只是傳遞的參數類型不同。還有一些變體不要求傳遞參數化的參數,因為他們被設計成傳遞制定類型參數,并返回制定類型的結果。例如,IntToDoubleFunction 接受int類型參數并返回double類型結果,還有區別是,使用applyAsDouble 替代apply方法,下面的例子實現攝氏溫度轉換成華氏溫度。
import java.util.function.IntToDoubleFunction;public class IntToDoubleFunctionDemo1 { public static void main(String[] args) { IntToDoubleFunction celciusToFahrenheit = (input) -> 1.8 * input + 32; int celcius = 100; double fahrenheit = celciusToFahrenheit.applyAsDouble(celcius); System.out.println(celcius + "/u2103" + " = " + fahrenheit + "/u2109/n"); }}
控制臺輸出:100℃ = 212.0℉LongToDoubleFunction and LongToIntFunction 用法與IntToDoubleFunction類似。UnaryOperator 是 Function 的另一種特殊實現,他的操作符類型與返回類型一樣。它的定義如下:  public interfaceUnaryOperator<T> extends Function<T,T>BinaryOperator 是 BiFunction 的一特殊實現,要求所有參數類型一樣并與返回類型一樣。

Predicate

Predicate是根據傳遞參數的值返回boolean值。它有一個抽象方法test。

舉例,下面的PredicateDemo1 類 定義一個Predicate 來判斷傳遞進去的字符串每一個字符是否全是數字。

 1 import java.util.function.Predicate; 2  3 public class PredicateDemo1 { 4     public static void main(String[] args) { 5         Predicate<String> numbersOnly = (input) -> { 6             for (int i = 0; i < input.length(); i++) { 7                 char c = input.charAt(i); 8                 if ("0123456789".indexOf(c) == -1) { 9                     return false;10                 }11             }12             return true;13         };14         15         System.out.println(numbersOnly.test("12345"));// true16         System.out.println(numbersOnly.test("100a")); // false17     }18 }

Supplier

Supplier沒有參數但返回一個值。要實現這個接口必須重寫get抽象方法并返回參數化類型的實例。

下面的例子,Supplier定義了一個返回 數字隨機數,并使用for循環打印5個隨機數。

import java.security.SecureRandom;import java.util.function.Supplier;public class SupplierDemo1 {    public static void main(String[] args) {    Supplier<Integer> oneDigitRandom = () -> {        SecureRandom random = new SecureRandom();        return random.nextInt(10);    };    for (int i = 0; i < 5; i++) {        System.out.println(oneDigitRandom.get());    }    }}

還有一些Supplier的變體,例如DoubleSupplier (返回 Double), IntSupplier 和LongSupplier.

Consumer

Consumer是一個沒有返回值的操作,它有一個抽象方法accept。

下面的例子使用ConSumer傳遞一個字符串參數,根據字符串的長度,和使用Function返回的空格的長度,最后把空格與字符串連接。

 1 import java.util.function.Consumer; 2 import java.util.function.Function; 3  4 public class ConsumerDemo1 { 5     public static void main(String[] args) { 6     Function<Integer, String> spacer = (count) -> { 7         StringBuilder sb = new StringBuilder(count); 8         for (int i = 0; i < count; i++) { 9         sb.append(" ");10         }11         return sb.toString();12     };13 14     int lineLength = 60; // characters15     Consumer<String> printCentered = (input) -> {16         int length = input.length();17         String spaces = spacer.apply((lineLength - length) / 2);18         System.out.println(spaces + input);19     };20 21     printCentered.accept("A lambda expression a day");22     printCentered.accept("makes you");23     printCentered.accept("look smarter");24     }25 }


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 星座| 平邑县| 铜川市| 临颍县| 凤凰县| 花莲市| 彭州市| 沈阳市| 应用必备| 会宁县| 秭归县| 塔河县| 池州市| 分宜县| 抚顺县| 沙洋县| 界首市| 曲周县| 张家川| 巫山县| 黔西| 卢湾区| 全南县| 渑池县| 横峰县| 金寨县| 宜州市| 海原县| 丰台区| 滦南县| 延安市| 石阡县| 湾仔区| 卢湾区| 武隆县| 奇台县| 遂宁市| 太和县| 河源市| 甘孜县| 清镇市|