日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java函数式接口看这一篇就够了

發布時間:2024/10/14 java 151 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java函数式接口看这一篇就够了 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄:
1.函數式接口的基本概念和格式
2.函數式編程
3.函數式接口作為方法的參數和方法的返回值
4.常用函數式接口

1.函數式接口的基本概念和格式

1.函數式接口的基本概念:

函數式接口在Java中是指:有且僅有一個抽象方法的接口。
函數式接口,即適用于函數式編程場景的接口。而Java中的函數式編程體現就是Lambda,所以函數式接口就是可 以適用于Lambda使用的接口。只有確保接口中有且僅有一個抽象方法,Java中的Lambda才能順利地進行推導。

如果對Lambda表達式不是很清除那么可以參照這一篇博客:Lambda表達式詳解

介紹一個語法糖概念:

語法糖:是指使用更加方便,但是原理不變的代碼語法。例如在遍歷集合時使用的for-each語法,其實 底層的實現原理仍然是迭代器,這便是“語法糖”。從應用層面來講,Java中的Lambda可以被當做是匿名內部 類的“語法糖”,但是二者在原理上是不同的。

2.格式:

只要滿足有一個抽象方法的接口即可,當然也可以包含其他的方法(默認靜態私有等等)

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

由于接口中默認類型為public abstract 所以帶不帶都行

3.@FunctionalInterface注解:

Java 8中專門為函數式接口引入了一個新的注解: @FunctionalInterface。該注 解可用于一個接口的定義上

@FunctionalInterfacepublic interface MyFunctionalInterface{ void myMethod(); }

我們這一個注解當我們在定義函數式接口的時候發送了錯誤,那么注解的編譯就不通過:
當我們去掉一個抽象的方法的時候就,注意就會正常通過編譯:

一旦使用該注解來定義接口,編譯器將會強制檢查該接口是否確實有且僅有一個抽象方法,否則將會報錯。需要注 意的是,即使不使用該注解,只要滿足函數式接口的定義,這仍然是一個函數式接口,使用起來都一樣。

2.函數式編程

1.Lambda表達式的延遲執行
看一段代碼:

public class Demo01Logger { private static void log(int level, String msg) { if (level == 1) { System.out.println(msg); } }public static void main(String[] args) { String msgA = "Hello";String msgB = "World"; String msgC = "Java"; log(1, msgA + msgB + msgC); } }

分析一下這段代碼,發現存在浪費,首先log方法傳進兩個參數,第一個參數是一個數字,第二個參數是一個拼接后的字符串,那么正常調用的時候我們就要先把字符串拼接好后再調用log函數,如果第一個參數不是1,那么拼接字符串就顯得沒用,白拼接了,這樣就造成了浪費,這時候就可以使用Lambda解決

想要解決問題,那么首先我們了解Lambda的使用特點和前提:

1.使用特點:延遲加載
2.使用前提:必須存在函數式接口

具體解決的代碼實現:

package untl1; public class Demo02LoggerLambda {private static void log(int level, MessageBuilder builder){if (level == 1){System.out.println(builder.buildMessage());}}public static void main(String[] args){String msgA = "Hello";String msgB = "World";String msgC = "Java";log(1, ()-> msgA+msgB+msgC);} } @FunctionalInterface interface MessageBuilder {String buildMessage(); }

此段代碼就完美的解決上述問題,那么,我們如何證實在第一個參數不是1的時候不進行字符串的拼接呢,我們可以在第二個參數加一個書輸出語句即

package untl1; public class Demo02LoggerLambda {private static void log(int level, MessageBuilder builder){if (level == 1){System.out.println(builder.buildMessage());}}public static void main(String[] args){String msgA = "Hello";String msgB = "World";String msgC = "Java";log(1, ()-> {System.out.println("我第一個參數是1");return msgA+msgB+msgC+1;});log(2, ()-> {System.out.println("我第一個參數不是1");return msgA+msgB+msgC+2;});} } @FunctionalInterface interface MessageBuilder {String buildMessage(); } 運行結果: 我第一個參數是1 HelloWorldJava1

3.函數式接口作為方法的參數和方法的返回值

作為方法的參數,上邊修正過的例子就是,作為方法的返回值如下例:

package untl1; public class Demo02LoggerLambda {private static MessageBuilder log(){return (a,b)->{return a+b;};}public static void main(String[] args){MessageBuilder a=log();System.out.println(a.buildMessage("hello","world"));} } @FunctionalInterface interface MessageBuilder {String buildMessage(String a,String b); } 運行結果: helloworld

注意return中的a和b是兩個變量名稱,可以隨意更改

4.常用函數式接口

1.supplier接口:
(1) 簡介:

java.util.function.Supplier<T> 接口僅包含一個無參的方法: T get() 。用來獲取一個泛型參數指定類型的對 象數據。由于這是一個函數式接口,這也就意味著對應的Lambda表達式需要“對外提供”一個符合泛型類型的對象 數據,supplier接口又被稱為生產型接口,指定接口是什么類型,那么接口的get方法就會產生一個什么類型的數據類型

(2)例子:

package untl1; import java.util.function.Supplier; public class MySupplier {public static String getString(Supplier<String> sup){return sup.get();}public static void main(String[] args) {String str=getString(()->"helloworld");System.out.println(str);}} 運行結果: helloworld

2.Consumer接口:
(1)簡介:

java.util.function.Consumer<T> 接口則正好與Supplier接口相反,它不是生產一個數據,而是消費一個數據, 其數據類型由泛型決定。Consumer 接口中包含抽象方法 void accept(T t) ,意為消費一個指定泛型的數據。,至于具體怎么消費如何消費需要自定義(輸出或者計算等等…)

(2)l例子:

package untl1; import java.util.function.Consumer; public class MyConsumer {public static void method(String name, Consumer<String> con){con.accept(name);}public static void main(String[] args) {method("我是帥哥",(String name1)-> System.out.println(name1));} }

(3).Consumer默認方法andThen

如果一個方法的參數和返回值全都是 Consumer 類型,那么就可以實現效果:消費數據的時候,首先做一個操作, 然后再做一個操作,實現組合。而這個方法就是 Consumer 接口中的default方法 andThen 。下面是JDK的源代碼:

default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after);return (T t)> {accept(t); after.accept(t); }; }

其實andThen方法簡單來說就是把兩個Consumer接口組合在一起,在分別對數據進行消費
下面我們不使用andThen和使用andThen的兩個例子做對比:
例子1(不使用andThen):

package untl1; import java.util.function.Consumer; public class MyConsumer {public static void method(String str, Consumer<String> a,Consumer<String> b){a.accept(str);b.accept(str);}public static void main(String[] args) {method("hello",(String a)-> System.out.println(a),(String b)-> System.out.println(b.toUpperCase()));}} 運行結果: hello HELLO

我們使用andThen之后:

package untl1; import java.util.function.Consumer; public class MyConsumer {public static void method(String str, Consumer<String> a,Consumer<String> b){a.andThen(b).accept(str);}public static void main(String[] args) {method("hello",(String a)-> System.out.println(a),(String b)-> System.out.println(b.toUpperCase()));}} 運行結果和上邊的一樣

上述代碼由于是a連接b那么先執行a消費數據,然后再執行消費數據
3.Predicate接口:
(1)簡介;

有時候我們需要對某種類型的數據進行判斷,從而得到一個boolean值結果。這時可以使用 java.util.function.Predicate<T>接口。Predicate 接口中包含一個抽象方法: boolean test(T t) 。

(2)例子:

package untl1; import java.util.function.Predicate; public class MyPredicate {public static boolean checkString(String str, Predicate<String> pre){return pre.test(str);}public static void main(String[] args) {String str="abc";boolean b=checkString(str,a->a.length()>6);System.out.println(b);} } 運行結果: false

(3)默認方法and:

既然是條件判斷,就會存在與、或、非三種常見的邏輯關系。其中將兩個 Predicate 條件使用“與”邏輯連接起來實 現“并且”的效果時,可以使用default方法 and。其JDK源碼為

default Predicate<T> and(Predicate<? super T> other) {Objects.requireNonNull(other);return (t)> test(t) && other.test(t); }

例子:
我么判斷一個字符串里邊長度是不是為5,里邊是不是包含a這個字符:

package untl1; import java.util.function.Predicate; public class MyPredicate {public static boolean checkString(String str, Predicate<String> a,Predicate<String> b){return a.and(b).test(str);//其實就相當于return a.test(str)&&b.test(str)}public static void main(String[] args) {boolean a= checkString("abc",str->str.length()==5,str->str.contains("a") );System.out.println(a);} } 運算結果: false

(4)默認方法or:

與 and 的“與”類似,默認方法 or 實現邏輯關系中的“或”。

例子:

package untl1; import java.util.function.Predicate; public class MyPredicate {public static boolean checkString(String str, Predicate<String> a,Predicate<String> b){return a.or(b).test(str);//其實就相當于return a.test(str)||b.test(str)}public static void main(String[] args) {boolean a= checkString("abc",str->str.length()==5,str->str.contains("a") );System.out.println(a);} } 運行結果: true

(5)默認方法negate:

“或”已經了解了,剩下的“非”(取反)也會簡單。

例子:

package untl1; import java.util.function.Predicate; public class MyPredicate {public static boolean checkString(String str, Predicate<String> a){return a.negate().test(str);}public static void main(String[] args) {boolean a= checkString("abc",str->str.length()==5);System.out.println(a);} } 運行結果: true

5.Function接口:
(1)簡介

java.util.function.Function<T,R> 接口用來根據一個類型的數據得到另一個類型的數據,前者稱為前置條件, 后者稱為后置條件。Function 接口中最主要的抽象方法為:R apply(T t) ,根據類型T的參數獲取類型R的結果。 使用的場景例如:將 String 類型轉換為 Integer 類型。

(2)
例子:

package untl1; import java.util.function.Function; public class MyFunction {public static void change(String str, Function<String,Integer> fun){int in=fun.apply(str);//自動拆箱System.out.println(in+1);}public static void main(String[] args) {String str="1234";change(str,a-> Integer.parseInt(a));}} 運行結果: 1235

(3)默認方法andThen:

同樣進行組合操作:

例子:
我們把String類型的123轉換成Integer加上10,再轉換成String類型:

package untl1; import java.util.function.Function; public class MyFunction {public static void change(String str, Function<String,Integer> fun1,Function<Integer,String> fun2){String str1=fun1.andThen(fun2).apply(str);System.out.println(str1);}public static void main(String[] args) {String str="123";change(str,a-> Integer.parseInt(a)+10,b->b+"");}} 運行結果: 133

總結

以上是生活随笔為你收集整理的Java函数式接口看这一篇就够了的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。