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體}中只有一句語句時,並且這個語句還是一個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體中使用上了,要麼是作爲調用方法的對象,要麼是作爲方法的實參。
(2) 當Lambda表達式是創建一個數組對象,並且滿足Lambda表達式形參,正好是給創建這個數組對象的長度
構造器引用的語法格式:
類名::new
數組類型名::new
Stream API 提供了一種高效且易於使用的處理數據的方式。
Stream 是 Java8 中處理集合的關鍵抽象概念,它可以指定你希望對集合進行的多種操作,可以執行非常複雜的查找、過濾和映射數據等操作。
Stream 是數據渠道,用於操作數據源(集合、數組等)所存儲的元素序列。“集合指的是負責存儲數據,Stream流指的是計算,負責處理數據!”
注意:
②Stream 不會改變源對象。每次處理都會返回一個持有結果的新Stream。
③Stream 操作是延遲執行的。這意味着他們會等到需要結果的時候才執行。
Stream 的操作三個步驟:
1- 創建 Stream:通過一個數據源(如:集合、數組),獲取一個流
3- 終止操作:一旦執行終止操作,就執行中間操作鏈,最終產生結果並結束Stream。
1、創建 Stream方式一:通過集合
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>
4、創建 Stream方式四:創建無限流
可以使用靜態方法 Stream.iterate() 和 Stream.generate(), 創建無限流。
public static<T> Stream<T>
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 的值,或者僅僅保存 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)配合使用,
(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,而有值的對象則把其值看作對應域的值。