Java語法進階16-Lambda-Stream-Optional

Lambda

  大年初二,大門不出二門不邁。繼續學習!

函數式接口

  Lambda表達式其實就是實現SAM接口的語法糖,所謂SAM接口就是Single Abstract Method,即該接口中只有一個抽象方法需要實現,當然該接口可以包含其他非抽象方法。

   它關注方法具備什麼樣的功能,強調做什麼,而不是以什麼形式做

  • 面向對象的思想:

    • 做一件事情,找一個能解決這個事情的對象,調用對象的方法,完成事情.

  • 函數式編程思想:

    • 只要能獲取到結果,誰去做的,怎麼做的都不重要,重視的是結果,不重視過程

自定義函數式接口

   只要確保接口中有且僅有一個抽象方法即可

修飾符 interface 接口名稱 {
    public abstract 返回值類型 方法名稱(可選參數信息);// public abstract 是可以省略的
    // 其他非抽象方法內容
}

消費型接口

  消費型接口的抽象方法特點:有形參,但是返回值類型是void

接口名抽象方法描述
Consumer<T> void accept(T t) 接收一個對象用於完成功能
BiConsumer<T,U> void accept(T t, U u) 接收兩個對象用於完成功能
DoubleConsumer void accept(double value) 接收一個double值
IntConsumer void accept(int value) 接收一個int值
LongConsumer void accept(long value) 接收一個long值
ObjDoubleConsumer<T> void accept(T t, double value) 接收一個對象和一個double值
ObjIntConsumer<T> void accept(T t, int value) 接收一個對象和一個int值
ObjLongConsumer<T> void accept(T t, long value) 接收一個對象和一個long值

供給型接口

  供給型接口的抽象方法特點:無參,但是有返回值

接口名抽象方法描述
Supplier<T> T get() 返回一個對象
BooleanSupplier boolean getAsBoolean() 返回一個boolean值
DoubleSupplier double getAsDouble() 返回一個double值
IntSupplier int getAsInt() 返回一個int值
LongSupplier long getAsLong() 返回一個long值

判斷型接口

  判斷型接口的抽象方法特點:有參,但是返回值類型是boolean結果

接口名抽象方法描述
Predicate<T> boolean test(T t) 接收一個對象
BiPredicate<T,U> boolean test(T t, U u) 接收兩個對象
DoublePredicate boolean test(double value) 接收一個double值
IntPredicate boolean test(int value) 接收一個int值
LongPredicate boolean test(long value) 接收一個long值

功能型接口

  功能型接口的抽象方法特點:既有參數又有返回值

接口名抽象方法描述
Function<T,R> R apply(T t) 接收一個T類型對象,返回一個R類型對象結果
UnaryOperator<T> T apply(T t) 接收一個T類型對象,返回一個T類型對象結果
DoubleFunction<R> R apply(double value) 接收一個double值,返回一個R類型對象
IntFunction<R> R apply(int value) 接收一個int值,返回一個R類型對象
LongFunction<R> R apply(long value) 接收一個long值,返回一個R類型對象
ToDoubleFunction<T> double applyAsDouble(T value) 接收一個T類型對象,返回一個double
ToIntFunction<T> int applyAsInt(T value) 接收一個T類型對象,返回一個int
ToLongFunction<T> long applyAsLong(T value) 接收一個T類型對象,返回一個long
DoubleToIntFunction int applyAsInt(double value) 接收一個double值,返回一個int結果
DoubleToLongFunction long applyAsLong(double value) 接收一個double值,返回一個long結果
IntToDoubleFunction double applyAsDouble(int value) 接收一個int值,返回一個double結果
IntToLongFunction long applyAsLong(int value) 接收一個int值,返回一個long結果
LongToDoubleFunction double applyAsDouble(long value) 接收一個long值,返回一個double結果
LongToIntFunction int applyAsInt(long value) 接收一個long值,返回一個int結果
DoubleUnaryOperator double applyAsDouble(double operand) 接收一個double值,返回一個double
IntUnaryOperator int applyAsInt(int operand) 接收一個int值,返回一個int結果
LongUnaryOperator long applyAsLong(long operand) 接收一個long值,返回一個long結果
     
BiFunction<T,U,R> R apply(T t, U u) 接收一個T類型和一個U類型對象,返回一個R類型對象結果
BinaryOperator<T> T apply(T t, T u) 接收兩個T類型對象,返回一個T類型對象結果
ToDoubleBiFunction<T,U> double applyAsDouble(T t, U u) 接收一個T類型和一個U類型對象,返回一個double
ToIntBiFunction<T,U> int applyAsInt(T t, U u) 接收一個T類型和一個U類型對象,返回一個int
ToLongBiFunction<T,U> long applyAsLong(T t, U u) 接收一個T類型和一個U類型對象,返回一個long
DoubleBinaryOperator double applyAsDouble(double left, double right) 接收兩個double值,返回一個double結果
IntBinaryOperator int applyAsInt(int left, int right) 接收兩個int值,返回一個int結果
LongBinaryOperator long applyAsLong(long left, long right) 接收兩個long值,返回一個long結果

Lambda表達式語法

  其本質上,Lambda表達式是用於實現【函數式接口】的“抽象方法”

Lambda表達式語法格式

(形參列表) -> {Lambda體}

說明:

  • (形參列表)它就是你要賦值的函數式接口的抽象方法的 (形參列表),照抄

  • {Lambda體}就是實現這個抽象方法的方法體

  • -> 稱爲Lambda操作符(減號和大於號中間不能有空格,而且必須是英文狀態下半角輸入方式)

優化:Lambda表達式可以精簡

  • 當{Lambda體}中只有一句語句時,可以省略{}和{;}

  • 當{Lambda體}中只有一句語句時,並且這個語句還是一個return語句,那麼return也可以省略,但是如果{;}沒有省略的話,return是不能省略的

  • (形參列表)的類型可以省略

  • 當(形參列表)的形參個數只有一個,那麼可以把數據類型和()一起省略,但是形參名不能省略

  • 當(形參列表)是空參時,()不能省略

ArrayList<String> list = new ArrayList<>();
list.forEach((li) -> System.out.println("li = " + li));//void forEach(Consumer<? super T> action)

方法引用

  當 Lambda 體滿足一些特殊的情況時,還可以再簡化

    (1)Lambda體只有一句語句,並且是通過調用一個對象的/類的現有的方法來完成的

    (2)並且Lambda表達式的形參正好是給該方法的實參

  方法引用的語法格式:

    (1)實例對象名::實例方法

    (2)類名::靜態方法

    (3)類名::實例方法

  說明:

    :: 稱爲方法引用操作符(兩個 中間不能有空格,而且必須英文狀態下半角輸入)

    Lambda表達式的形參列表,全部在Lambda體中使用上了,要麼是作爲調用方法的對象,要麼是作爲方法的實參。

    在整個Lambda體中沒有額外的數據。

構造器引用

  (1)當Lambda表達式是創建一個對象,並且滿足Lambda表達式形參,正好是給創建這個對象的構造器的實參列表。

  (2) 當Lambda表達式是創建一個數組對象,並且滿足Lambda表達式形參,正好是給創建這個數組對象的長度

  構造器引用的語法格式:

    類名::new

    數組類型名::new

Stream

  Stream API 提供了一種高效且易於使用的處理數據的方式。

  Stream 是 Java8 中處理集合的關鍵抽象概念,它可以指定你希望對集合進行的多種操作,可以執行非常複雜的查找、過濾和映射數據等操作。

  Stream 是數據渠道,用於操作數據源(集合、數組等)所存儲的元素序列。“集合指的是負責存儲數據,Stream流指的是計算,負責處理數據!”

注意

  ①Stream 自己不會存儲元素

  ②Stream 不會改變源對象。每次處理都會返回一個持有結果的新Stream。

  ③Stream 操作是延遲執行的。這意味着他們會等到需要結果的時候才執行。

Stream 的操作三個步驟:

  1- 創建 Stream:通過一個數據源(如:集合、數組),獲取一個流

  2- 中間操作:中間操作是個操作鏈,對數據源的數據進行n次處理,但是在終結操作前,並不會真正執行。

  3- 終止操作:一旦執行終止操作,就執行中間操作鏈,最終產生結果並結束Stream。

創建Stream

  1、創建 Stream方式一:通過集合

    Java8 中的 Collection 接口被擴展,提供了兩個獲取流的方法:

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

      public default Stream<E> parallelStream() : 返回一個並行流

  2、創建 Stream方式二:通過數組

    Java8 中的 Arrays 的靜態方法 stream() 可以獲取數組流:

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

     還有重載形式,能夠處理對應基本類型的數組

  3、創建 Stream方式三:通過 Stream.of()

    可以調用Stream類靜態方法 of(), 通過顯示值創建一個流。它可以接收任意數量的參數。

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

  4、創建 Stream方式四:創建無限流

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

      public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f):返回一個無限流

      public static<T> Stream<T> generate(Supplier<T> s) :返回一個無限流

中間操作

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

方 法描 述
filter(Predicate p) 篩選,接收 Lambda , 從流中排除某些元素
distinct() 去除,通過流所生成元素的equals() 去除重複元素
limit(long maxSize) 截斷流,使其元素不超過給定數量
skip(long n) 跳過元素,返回一個扔掉了前 n 個元素的流。若流中元素不足 n 個,則返回一個空流。與 limit(n) 互補
peek(Consumer action) 接收Lambda,對流中的每個數據執行Lambda體操作
sorted() 產生一個新流,其中按自然順序排序
sorted(Comparator com) 產生一個新流,其中按比較器順序排序
map(Function f) 接收一個函數作爲參數,該函數會被應用到每個元素上,並將其映射成一個新的元素。
mapToDouble(ToDoubleFunction f) 接收一個函數作爲參數,該函數會被應用到每個元素上,產生一個新的 DoubleStream。
mapToInt(ToIntFunction f) 接收一個函數作爲參數,該函數會被應用到每個元素上,產生一個新的 IntStream。
mapToLong(ToLongFunction f) 接收一個函數作爲參數,該函數會被應用到每個元素上,產生一個新的 LongStream。
flatMap(Function f) 接收一個函數作爲參數,將流中的每個值都換成另一個流,然後把所有流連接成一個流

終結操作

  終端操作會從流的流水線生成結果。其結果可以是任何不是流的值,例如:List、Integer,甚至是 void。流進行了終止操作後,不能再次使用。

方法描述
boolean allMatch(Predicate p) 檢查是否匹配所有元素
boolean anyMatch(Predicate p) 檢查是否至少匹配一個元素
boolean noneMatch(Predicate p) 檢查是否沒有匹配所有元素
Optional<T> findFirst() 返回第一個元素
Optional<T> findAny() 返回當前流中的任意元素
long count() 返回流中元素總數
Optional<T> max(Comparator c) 返回流中最大值
Optional<T> min(Comparator c) 返回流中最小值
void forEach(Consumer c) 迭代
T reduce(T iden, BinaryOperator b) 可以將流中元素反覆結合起來,得到一個值。返回 T
U reduce(BinaryOperator b) 可以將流中元素反覆結合起來,得到一個值。返回 Optional<T>
R collect(Collector c) 將流轉換爲其他形式。接收一個 Collector接口的實現,用於給Stream中元素做彙總的方法

  Collector 接口中方法的實現決定了如何對流執行收集的操作(如收集到 List、Set、Map)。另外, Collectors 實用類提供了很多靜態方法,可以方便地創建常見收集器實例。

Optional<T>

  爲了解決空指針異常,Optional 提供很多有用的方法,這樣我們就不用顯式進行空值檢測。

  Optional實際上是個容器:它可以保存類型 T 的值,或者僅僅保存 null。

API

  1、如何創建Optional對象?或者說如何用Optional來裝值對象或null值

    (1)static <T> Optional<T> empty() :用來創建一個空的Optional

    (2)static <T> Optional<T> of(T value) :用來創建一個非空的Optional

    (3)static <T> Optional<T> ofNullable(T value) :用來創建一個可能是空,也可能非空的Optional

  2、如何從Optional容器中取出所包裝的對象呢?

    (1)T get() :要求Optional容器必須非空

        T get()與of(T value)使用是安全的

    (2)T orElse(T other) :

        orElse(T other) 與 ofNullable(T value)配合使用,

        如果Optional容器中非空,就返回所包裝值,如果爲空,就用orElse(T other)other指定的默認值(備胎)代替

    (3)T orElseGet(Supplier<? extends T> other) :

        如果Optional容器中非空,就返回所包裝值,如果爲空,就用Supplier接口的Lambda表達式提供的值代替

    (4)<X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)

        如果Optional容器中非空,就返回所包裝值,如果爲空,就拋出你指定的異常類型代替原來的NoSuchElementException

  3、其他方法

    (1)boolean isPresent() :判斷Optional容器中的值是否存在

    (2)void ifPresent(Consumer<? super T> consumer) :

        判斷Optional容器中的值是否存在,如果存在,就對它進行Consumer指定的操作,如果不存在就不做

    (3)<U> Optional<U> map(Function<? super T,? extends U> mapper)

        判斷Optional容器中的值是否存在,如果存在,就對它進行Function接口指定的操作,如果不存在就不做

重要的一點是 Optional 不是 Serializable。因此,它不應該用作類的字段。

 Jackson 庫支持把 Optional 當作普通對象。也就是說,Jackson 會把空對象看作 null,而有值的對象則把其值看作對應域的值。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章