java8 注解: @FunctionalInterface (函數式接口)

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。

Java8提倡函數式編程,因而新增了一個函數式接口。函數式接口保證了函數式編程,同時也保證了能夠兼容以前的java版本。

?????函數式接口的定義

?????在java8中,滿足下面任意一個條件的接口都是函數式接口:

1、被@FunctionalInterface注釋的接口,滿足@FunctionalInterface注釋的約束。

2、沒有被@FunctionalInterface注釋的接口,但是滿足@FunctionalInterface注釋的約束。

?

?????@FunctionalInterface注釋的約束:

1、接口有且只能有個一個抽象方法,只有方法定義,沒有方法體

2、在接口中覆寫Object類中的public方法,不算是函數式接口的方法。

下面三個接口都是函數式接口:

//接口一
@FunctionalInterface
public interface FunctionInterfaceTest {String getInfo(String input);@OverrideString toString(); ?//Object中的方法@Overrideboolean equals(Object obj); //Object中的方法
}
//接口二
@FunctionalInterface
public interface FunctionInterfaceTest {String getInfo(String input);}//接口三
public interface FunctionInterfaceTest {String getInfo(String input);}


??????函數式接口實例的創建

函數式接口實例的創建有三種方式:1、lambda表達式;2、方法引用;3、構造方法引用。


public class Main {public static void main(String[] args) {/*** 1、lambda表達式* 這種形式最為直觀,lambda表達式,接收一個String類型的參數,返回一個String類型的結果。* 完全符合函數式接口FunctionInterfaceTest的定義*/FunctionInterfaceTest functionInterfaceTest1 = item -> item+1; ?/*** 2、方法引用* Main方法當中的getInstance和getMessage方法接收一個參數,返回一個結果。符合函數式接口* FunctionInterfaceTest的定義。* 函數式接口只是定義了個方法的約定(接收一個String類型的參數,返回一個String類型的結果),* 而對于方法內部進行何種操作則并沒有做任何的限制。在這點上,跟java以前的版本中的實現類與接口之間的* 關系很類似。不同的是,函數式接口更偏重于計算過程,約束了一個計算過程的輸入和輸出。* 這種約束計算過程的輸入和輸出的形式的好處可以看一下joinStr方法。*/FunctionInterfaceTest functionInterfaceTest2 = Main::getInstance; ?//方法引用FunctionInterfaceTest functionInterfaceTest3 = Main::getMessage; ?//方法引用String msg1 = joinStr("你好",functionInterfaceTest2); //輸出:你好!世界String msg2 = joinStr("你好",functionInterfaceTest3); //輸出:世界,你好!System.out.println(msg1);System.out.println(msg2);//還有更簡單的寫法,高度抽象化,具體處理由使用者自己決定String msg3 = joinStr("你好",item ->item+"!世界"); //輸出:你好!世界String msg4 = joinStr("你好",item ->"世界,"+ item+"!"); //輸出:世界,你好!System.out.println(msg3);System.out.println(msg4);/*** 3、構造方法引用* 構造函數的結構:接收輸入參數,然后返回一個對象。這種約束跟函數式接口的約束很像。* 所以只要“輸入參數類型”與“輸出參數類型”跟FunctionInterfaceTest中的方法約束相同,* 就可以創建出FunctionInterfaceTest接口的實例,如下,String的構造方法中有* new String(str)的構造方法,所以可以得到實例。* 這里存在一個類型推斷的問題,JDK的編譯器已經幫我們自動找到了只有一個參數,且是String類型的構造方法。* 這就是我們直接String::new,沒有指定使用哪一個構造方法,卻可以創建實例的原因*/FunctionInterfaceTest functionInterfaceTest4 = String::new; //方法引用}public static String getInstance(String item){return item+"!世界";}public static String getMessage(String massage){return "世界,"+ massage+"!";}public ?static String joinStr(String str,FunctionInterfaceTest functionTest){return functionTest.getInfo(str);}


???????java8中常用的函數式接口:

常用的函數式接口主要有四種類型,是通過其輸入和輸出的參數來進行區分的。定義了編碼過程中主要的使用場景。

public class FunctionalInterfaceMain {public static void main(String[] args) {/*** 先看看如何創建它們*/Function<String,String> function1 = item -> item +"返回值";Consumer<String> function2 = iterm -> {System.out.println(iterm);};//lambda語句,使用大括號,沒有return關鍵字,表示沒有返回值Predicate<String> function3 = iterm -> "".equals(iterm);Supplier<String> function4 = () -> new String("");/*** 再看看怎么使用* demo釋義:* 1、創建一個String類型的集合* 2、將集合中的所有元素的末尾追加字符串'1'* 3、選出長度大于2的字符串* 4、遍歷輸出所有元素*/List<String> list = Arrays.asList("zhangsan","lisi","wangwu","xiaoming","zhaoliu");list.stream().map(value -> value + "1") //傳入的是一個Function函數式接口.filter(value -> value.length() > 2) //傳入的是一個Predicate函數式接口.forEach(value -> System.out.println(value)); //傳入的是一個Consumer函數式接口}}

? ? 在實際使用中,我們往往會輸入多個參數,而不是一個參數。針對于多個參數的計算,最終都可以拆分兩個參數的運算,然后將兩個參數的運算結合起來。如:1+2+3+4 = 10,可以拆分為1+2 = 3,???3+3=6; ??6+4 = 10 三個步驟完成(在java中,是不允許一次返回多個值的)。

??????因此對于多個參數的操作也是如此。Java8中對于接收兩個參數的場景提供了相關的函數式接口。如下:

?public class FunctionalInterfaceTest {public static void main(String[] args) {/*** Bi類型的接口創建*/BiFunction<String, String, Integer> biFunction = (str1,str2) -> str1.length()+str2.length();BiConsumer<String, String> biConsumer = (str1,str2) -> System.out.println(str1+str2);BiPredicate<String, String> biPredicate = (str1,str2) -> str1.length() > str2.length();/*** Bi類型的接口使用*/int length = getLength("hello", "world", (str1,str2) -> str1.length() + str2.length()); //輸出10boolean boolean1 = getBoolean("hello", "world", (str1,str2) -> str1.length() > str2.length()); //輸出falseSystem.out.println(length);System.out.println(boolean1);noResult("hello", "world", (str1,str2) -> System.out.println(str1+" "+str2)); //沒有輸出}public ?static int getLength(String str1,String str2,BiFunction<String, String, Integer> function){return function.apply(str1, str2);}public static void noResult(String str1,String str2,BiConsumer<String, String> biConcumer){biConcumer.accept(str1, str2);}public static boolean getBoolean(String str1,String str2,BiPredicate<String, String> biPredicate){return biPredicate.test(str1, str2);}
}

???????關于多個參數值的使用,無論實在Function接口中,還是在BI類型的接口都提供了類似的操作。(注:java8中,接口的方法是可以有實現的,但需要default關鍵字修飾,這是其他版本的jdk沒有的特性)

1、??Function接口的andThen方法和compose方法

源碼:

default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {Objects.requireNonNull(before);return (V v) -> apply(before.apply(v));
}default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {Objects.requireNonNull(after);return (T t) -> after.apply(apply(t));
}

說明:

???????Compose方法:方法接收一個Function類型的參數,返回一個值。這也是一個標準的Function類型的定義。在compose方法內部也有一個apply方法。在執行compose方法中的apply方法之前,它先執行了before接口的apply方法,也是compose方法的輸入參數。然后將before方法執行的返回值作為compose中apply方法的輸入參數。實際上是形成了一種鏈式組合。

???????andThen方法:該方法與compose方法很類似。不同之處在于,andThen是先執行自身的apply方法,將apply的返回值作為after接口的輸入值。相對于compose方法,只是方向的不同

使用:

public class FunctionalInterfaceTest {public static void main(String[] args) {String str1 = getLength1("hello", value -> "hello的長度:"+value, value -> value.length()); //輸出:hello的長度:5System.out.println(str1);Integer result = getLength2("hello", value -> value, value -> value.length()); //輸出:5System.out.println(result);}public ?static String getLength1(String str1,Function<Integer, String> function1,Function<String,Integer> function2){/*** 這里一定要注意,function1和function2的參數類型。* function2的輸出類型與function1的輸入類型一定要一致,* 否則編譯不會通過*/return function1.compose(function2).apply(str1);}public ?static Integer getLength2(String str1,Function<String, String> function1,Function<String,Integer> function2){/*** 這里一定要注意,function1和function2的參數類型。* function1的輸出類型與function2的輸入類型一定要一致,(方向相反)* 否則編譯不會通過*/return function1.andThen(function2).apply(str1);}
}

相關接口:BiFunction

public static Integer getLength3(String str1,String str2,BiFunction<String, String, String> biFunction,Function<String,Integer> function){/*** biFunction只有andThen方法,這是有bi類型接口的特征決定的。* bi類型的接口需要接收兩個參數,然而java中是沒有返回兩個參數的情況的* 所以只有andThen方法,且其參數是function類型的,接收的是一個參數,* 返回一個值*/return biFunction.andThen(function).apply(str1, str2);
}

2、Consumer接口的andThen方法

源碼:

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


說明:
???????將輸入參數分別賦給andThen內部的accept方法和after內部的accept方法。After的計算在andThen之后,起到了后置連接的作用。在這里沒有compose方法,因為后置連接反過來就是前置連接,所以不需要一個多余的compose方法了。只需要在傳遞時,交換兩個consumer的順序即可。

使用:

public class FunctionalInterfaceTest {public static void main(String[] args) {noResult(Integer.valueOf(12),?value -> {int num = value + 12;System.out.println(num);},?value -> { int num = value + 24;System.out.println(num);}); //輸出:24,36}public static void noResult(Integer num,Consumer<Integer> consumer1,Consumer<Integer> consumer2){/*** 兩個consumer的接收類型必須一致*/consumer1.andThen(consumer2).accept(num);}
}?

相關接口:BiConsumer

public static void noResultBi(Integer num1,Integer num2,BiConsumer<Integer,Integer> consumer1,BiConsumer<Integer,Integer> consumer2){/*** 兩個consumer的接收類型必須一致*/consumer1.andThen(consumer2).accept(num1,num2);
}

3、 predicate接口的and、or、negate方法
源碼:

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

說明:

???????源碼已經很清晰了,就不一一說明了。分別是&&, || 和取反操作。

使用:

public class FunctionalInterfaceTest {public static void main(String[] args) {getBoolean("hello", value -> value.length() > 2, value -> value.length() > 6);}public static boolean getBoolean(String str1,Predicate< String> predicate1,Predicate< String> predicate2){boolean test = predicate1.or(predicate2).test(str1);System.out.println(test); //輸出truetest = predicate1.and(predicate2).test(str1);System.out.println(test);//輸出falsetest = predicate1.negate().test(str1);System.out.println(test);//輸出falsereturn test;}
}


相關接口:BiPreditcate

public static ?boolean getBooleanBi(String str1,String str2,BiPredicate<String, String> biPredicate1,BiPredicate<String, String> biPredicate2){boolean test = biPredicate1.and(biPredicate2).test(str1, str2);test = biPredicate1.negate().test(str1, str2);test = biPredicate1.or(biPredicate2).test(str1, str2);return test;
}

???????此外,java8針對原生類型int,long,double都提供了相應的函數式接口。如:DoubleConsumer, DoubleFunction,IntConsumer等等,使用方式都相同,見java.util.function包。


————————————————
本文為CSDN博主「漠風-」的原創文章,遵循 CC 4.0 BY-SA 版權協議。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/447510.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/447510.shtml
英文地址,請注明出處:http://en.pswp.cn/news/447510.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

寫給年輕程序員的一封信

很多年輕的程序員發emails給我&#xff0c;說希望能夠得到一些如何盡快躋身優秀程序員行列的建議和方法。關于這個問題&#xff0c;我已經有提到過很多次&#xff0c;現在已經沒什么可以補充的了。不過 為了滿足大家的要求&#xff0c;在這里我再詳細地歸納總結一下&#xff1a…

Docker中RocketMQ的安裝與使用

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 搜索RocketMQ的鏡像&#xff0c;可以通過docker的hub.docker.com上進行搜索&#xff0c;也可以在Linux下通過docker的search命令進行搜索…

大浪淘沙:不是所有的IT公司都以成功收場

本文列舉了50家創業公司沒有什么先后順序&#xff0c;最后顯示&#xff0c;其中21家是獨立公司&#xff0c;19家被收購了&#xff0c;4家正在走下坡路&#xff0c;6家已倒閉。但是我希望有更多的公司徹底倒閉&#xff0c;留下實力最強大的公司。公司倒閉也許是重新開始的標志。…

解決:阿里云ECS服務器 遠程連接不上、極慢 (主機監控的實現)

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 個人低配版的阿里云ECS服務器&#xff0c;突然發現用 Xshell 或者 git-bash 都連接不上... 第一反應發工單去問下為什么&#xff0c;然…

TIOBE 2014年7月編程語言排行榜:僅發布1月,Swift進Top 20!

摘要&#xff1a;TIOBE7月編程語言排行榜發布&#xff0c;本月最值得關注的是&#xff0c;蘋果公司在WWDC 2014上推出新的編程語言Swift&#xff0c;發布至今僅一月有余&#xff0c;Swift竟擠進TIOBE排行榜的Top 20&#xff0c;排名第16位。Swift能取得如此驕人的成績&#xff…

Math對象方法總結(向上取整、向下取整、四舍五入、取隨機數,取最大值、取最小值)

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。

Docker 方式安裝 gitlab ( 阿里云ECS )

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1.查找鏡像&#xff1a; docker search gitlab 2. 拉取鏡像&#xff1a; docker pull 鏡像名 我選擇的是搜索出來的第一個鏡像&…

商用的碼流分析工具/YUV viewer

目前市場上有一些商用的碼流分析工具是比較好的&#xff0c;能夠輔助我們進行各個標準的碼流分析&#xff1a; 1. Elecard StreamEye系列 可以分析H264/MPEG4/MPEG2的碼流&#xff0c;暫時不支持其它標準。 2. H264VISA 比較好的H264碼流分析工具 3. Vegas vegas是interra s…

生成多個 SSH-Key 、生成多個公鑰和私鑰

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 當有多個倉庫要同時使用時&#xff0c;需要配置多個公鑰、私鑰。于是就要先生成多個。 PS&#xff1a;初次生成參見文章&#xff1a;查…

使用Lucid Virtu在有獨立顯卡的情況下使用Intel硬件加速H.264編碼

在硬編碼領域&#xff0c;大家都知道CUDA技術對于H.264視頻編碼速度的提升。然而實際上常見的高清H.264視頻壓縮都不是用CUDA技術進行硬編碼&#xff0c;而是用傳統的x264進行軟編碼&#xff0c;因為通過CUDA硬編碼的視頻效果遠遠差于x264軟編碼壓縮出的視頻效果。隨著Intel Sa…

執行ssh-add時出現Could not open a connection to your authentication agent

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 若執行ssh-add /path/to/xxx.pem是出現這個錯誤:Could not open a connection to your authentication agent&#xff0c;則先執行如下命…

Intel硬件加速 VS CUDA完勝 視頻轉碼感受

對比試用平臺介紹 在體驗了酷睿 I5 2300 在3D游戲和多任務、高清播放等方面的突出性能后&#xff0c;今天我利用空閑時間針對酷睿 I5 2300在高清轉碼方面上與本人的舊平臺上對比了一下.&#xff0c;其結果也讓人感到震撼。好了閑話不多說了&#xff0c;先來給自己新舊PC做個介紹…

解決 : Shell 腳本 $‘\r‘: command not found 問題

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1.經查證&#xff0c;只是 Windows 的空行在 linux 中不識別&#xff0c;故需要用 dos2unix 來轉換。 2. 安裝 dos2unix&#xff0c;2 …

H.264 軟/硬編碼器 畫質量化分析評測

第1頁&#xff1a;前言——視頻壓縮無處不在H.264 或者說 MPEG-4 AVC 是目前使用最廣泛的高清視頻編碼標準&#xff0c;和上一代 MPEG-2、h.263/MPEG-4 Part4 相比&#xff0c;它的壓縮率大為提高&#xff0c;例如和 MPEG-2 相比&#xff0c;同樣的壓縮后畫面品質&#xff0c;h…

解決:Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.8.2:deploy (default-deploy)

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 執行 mvn clean deploy ... 想把 jar 包更新到私服倉庫&#xff0c;報錯&#xff1a; Failed to execute goal org.apache.maven.pl…

YV12 and NV12異同,

用videoCapture和IAMStreamConfig拿到的支持的格式列表。發現支持2中圖像格式&#xff0c;YV12和NV12。具體是怎么樣的內存分布不知道。查了些文檔。自己修改了幾個圖。看出了點端倪YV12先看看 http://www.fourcc.org/yuv.php 上比較標準的定義&#xff1a;YV12 This is the f…

上傳 jar 包到 nexus3、上傳本地 jar 包到 maven 私服

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1.登陸進入 nexus3&#xff0c;打開要上傳的倉庫目錄&#xff1a;maven-releases 2. 選擇要上傳的本地 jar 包&#xff0c;并填寫好對應…

從桌面到移動:異構計算翻天覆地的技術變革

摘要&#xff1a;在智能手機上&#xff0c;強大的計算單元&#xff0c;不僅僅是CPU一顆&#xff0c;還包含了GPU、DSP等器件。在傳統的臺式電腦中&#xff0c;異構計算已經說了好多年了。這篇文章有點長&#xff0c;但值得靜下心來慢慢閱讀。從桌面到移動&#xff0c;這是關于異…

集合源碼閱讀:ArrayList

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1.繼承關系&#xff1a;public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Clon…

全球最杰出的14位程序員

摘要&#xff1a;ITWorld整理全球最杰出的14位程序員&#xff0c;包括Jon Skeet、Linus Torvalds、Jeff Dean等。一起來看下讓我們膜拜的大神都有哪些&#xff1f; 近日&#xff0c;ITWorld整理全球最杰出的14位程序員&#xff0c;一起來看下讓我們膜拜的這些大神都有哪些&…