1.1函數式接口概述
函數式接口:有且僅有一個抽象方法的接口
Java中的函數式編程體現就是Lambda表達式,所以函數式接口就是可以適用於Lambda使用的接口
只有確保接口中有且僅有一個抽象方法, Java中的L ambda才能順利地進行推導
如何檢測一個接口是不是函數式接口呢?
@Functionallnterface放在接口定義的上方:
如果接口是函數式接口,編譯通過;如果不是,編譯失敗
注意
●我們自己定義 函數式接口的時候,@Functionallnterface是可選的, 就算我不寫這個注解,只要保證滿足函數式接口定
義的條件,也照樣是函數式接口。但是,建議加上該注解
1.2函數式接口作為方法的參數
需求
● 定義一個類(RunnableDemo),在類中提供兩個方法
一個方法是: startThread(Runnable r)方法參數Runnable是一 個函數式接口
一個方法是主方法,在主方法中調用startThread方法
如果方法的參數是一個函數式接口, 我們可以使用 ambda表達式作為參數傳遞
●startThread(0 -> System.out.println(Thread.currentThread0.getName0 + "線程啟動了));
package com.Test01; /* 定義一個類(RunnableDemo),在類中提供兩個方法 一個方法是: startThread(Runnable r) 方法參數Runnable是一 個函數式接口 一個方法是主方法,在主方法中調用startThread方法 */ public class RunnableDemo { public static void main(String[] args) { //在主方法中調用startThread方法 //采用匿名內部類的方式 startThread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + "線程啟動了"); } });
startThread (() -> System.out.println(Thread.currentThread().getName() + "線程啟動了"));
} private static void startThread(Runnable r) { // Thread t = new Thread(r); // t.start(); new Thread(r).start(); } }
1.3函數式接口作為方法的返回值
需求●定義一個類(ComparatorDemo), 在類中提供兩個方法
一個方法是: Comparator <String> getComparator()方法返回值C omparator是一個函數式接口
一個方法是主方法,在主方法中調用getComparator方法
如果方法的返回值是一個函數式接口,我們可以使用L ambda表達式作為結果返回
●private static Comparator <String> getComparator({
return (s1, s2) -> s1.length( - s2.length0;
}
package com.Test01; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; public class CommparatorDemo { public static void main(String[] args) { //構造使用場景 //定義集合 存儲字符串元素 ArrayList<String> array = new ArrayList<String>(); array.add("cccc"); array.add("aaa"); array.add("dd"); array.add("b"); System.out.println("排序前:" + array); Collections.sort(array, getComparator()); System.out.println("排序后:" + array); } public static Comparator<String> getComparator() { //返回該接口的實現類對象 //首先采用匿名內部類的方式 // Comparator<String> comp = new Comparator<String>() { // @Override // public int compare(String s1, String s2) { // return s1.length()-s2.length(); // } // }; // return comp; // return new Comparator<String>() { //// @Override //// public int compare(String s1, String s2) { //// return s1.length() - s2.length(); //// } //// }; // return (String s1,String s2) ->{ // return s1.length()-s2.length(); // }; return (s1, s2) -> s1.length() - s2.length(); } }
常用的4個函數式接口
Java 8在java.util.function包下預定義了大量的函數式接口供我們使用
我們重點來學習下面的4個接口
●Supplier接口
●Consumer接口
●Predicate接口、
●Function接口
1,Supplier接口
@FunctionalInterface
public interface Supplier<T>
package com.Test01; /* Supplier<T>:包含一個無參的方法 T get ():獲得結果 該方法不需要參數,它會按照某種實現邏輯(由Lambda表達式實現)返回一個數據 Supplier<T>接口也被稱為生產型接口,如果我們指定了接口的泛型是什么類型,那么接口中的get方法就會生產什么類型的數據供使用 */ import java.util.function.Supplier; public class SupplierDemo { public static void main(String[] args) { // String s = getString(() -> { // return "林青霞"; // }); String s = getString(() -> "林青霞"); System.out.println(s); } private static String getString(Supplier<String> sup) { return sup.get(); } }
package com.Test01; import java.util.function.Supplier; public class SupplierTest { public static void main(String[] args) { //定義一個數組 int[] arr = {15, 20, 3, 65, 45, 6}; int x = getMax(() -> { int Max = arr[0]; for (int i = 0; i < arr.length; i++) { if (Max < arr[i]) { Max = arr[i]; } } return Max; }); System.out.println(x); } private static int getMax(Supplier<Integer> sup) { return sup.get(); } }
,2,Consumer接口
@FunctionalInterface
public interface Consumer<T>
1.6 Consumer接口
Consumer<T>:包含兩個方法
void accept(T t): 對給定的參數執行此操作
default Consumer <T> andThen(Consumer after):返回一個組合的Consumer,依次執行此操作,然后執行after操作
●Consumer<T>接口也被稱為消費型接口,它消費的數據的數據類型由泛型指定
package com.Test01; /* Consumer<T>:包含兩個方法 void accept (T t): 對給定的參數執行此操作 default Consumer<T> andThen (Consumer after): 返回一個組合的Consumer, 依次執行此操作,然后執行after操作 Consumer<T>接口也被稱為消費型接口,它消費的數據的數據類型由泛型指定 / */ import java.util.function.Consumer; public class ConsumerDemo { public static void main(String[] args) { // Lamada表達式 // OperatorString("林青霞",(s) -> { // System.out.println(s); // }); // OperatorString("林青霞", (s) -> System.out.println(s)); //方法引用 OperatorString("林青霞", System.out::println); } //定義一個方法,消費一個字符串數據 private static void OperatorString(String name, Consumer<String> con) { con.accept(name); } }
Consumer練習
String[] strArray = {"林青霞, 30",”張曼玉,35", ”王祖賢, 33"};
字符串數組中有多條信息,請按照格式: "姓名: Xx,年齡: xX"的格式將信息打印出來
要求:
把打印姓名的動作作為第- -個Consumer接口的L ambdo實例
把打印年齡的動作作為第二個Consumer接口的L ambda實例
將兩個Consumer接口按照順序組合到一起使用
package com.Test01; /**/ import java.util.function.Consumer; public class ConsumerDemo02 { public static void main(String[] args) { String[] strArray = {"林青霞,30", "張曼玉,35", "王祖賢,33"}; printString(strArray, (String str) -> { String name = str.split(",")[0]; System.out.print("姓名:" + name); }, (String str) -> { int age = Integer.parseInt(str.split(",")[1]); System.out.println(",年齡:" + age); }); } private static void printString(String[] strArray, Consumer<String> con1, Consumer<String> con2) { for (String s : strArray) { con1.andThen(con2).accept(s); } } }
3, Predicate接口
@FunctionalInterface
public interface Predicate<T>
Predicate<T>:常用的四個方法
●boolean test(T t):對給定的參數進行判斷(判斷邏輯由L ambda表達式實現),返回一個布爾值
●default Predicate<T> negate():返回-一個邏輯的否定,對應邏輯非
●default Predicate<T> and(Predicate other):返回一個組合判斷,對應短路與
●default Predicate<T> or(Predicate other):返回一個組合判斷,對應短路或
----------- - -- - - - - - - - - -- - - - - - - - - - - - - -- - - -- - - - - - --
●Predicate<T>接口通常用於判斷參數是否滿足指定的條件
●boolean test(T t):對給定的參數進行判斷(判斷邏輯由L ambda表達式實現),返回一個布爾值
●default Predicate<T> negate():返回-一個邏輯的否定,對應邏輯非
如下演示
package com.Test01; /* Predicate<T>:常用的四個方法 boolean test (T t):對給定的參數進行判斷(判斷邏輯由Lambda表達式實現),返回一個布爾值 default Predicate<T> negate (): 返回一個邏輯的否定,對應邏輯非 Predicate<T>接口通常用於判斷參數是否滿足指定的條件 */ import java.util.function.Predicate; public class PredicateDemo01 { public static void main(String[] args) { // boolean b = checkString("hello", (String s) -> { // return s.length() > 8; // }); boolean b = checkString("hello", s -> s.length() > 8); System.out.println(b); } //判斷給定的字符串是否滿足要求 private static boolean checkString(String s, Predicate<String> pre) { // return pre.test(s); // return !pre.test(s);//不是標准非 return pre.negate().test(s);//接口提供的邏輯非的操作 } }
●default Predicate<T> and(Predicate other):返回一個組合判斷,對應短路與
●default Predicate<T> or(Predicate other):返回一個組合判斷,對應短路或
如下演示
package com.Test01; /* /* Predicate<T>: default Predicate<T> and (Predicate other): 返回一個組合判斷,對應短路與 default Predicate<T> or (Predicate other): 返回-一個組合判斷,對應短路或 */ import java.util.function.Predicate; public class PredicateDemo02 { public static void main(String[] args) { boolean b1 = checkString("hello", s -> s.length() > 8); //System.out.println(b1); boolean b2 = checkString("helloworld", s -> s.length() > 8); //System.out.println(b2); boolean b3 = checkStringandor("helloworld", s -> s.length() > 11, s -> s.length() < 15); System.out.println(b3); } //同一個字符串給出兩個不同的判斷條件,最后把這兩個判斷的結果做邏輯與運算的結果作為最終的結果 private static boolean checkStringandor(String s, Predicate<String> pre1, Predicate<String> pre2) { // boolean b1 = pre1.test(s); //// boolean b2 = pre2.test(s); //// boolean b = b1 || b2; //// return b; return pre1.or(pre2).test(s);//return pre1.and(pre2).test(s); } private static boolean checkString(String s, Predicate<String> pre) { //判定給定的字符串是否滿足要求 return pre.test(s); // } }
Predicate練習
String[ strArray= {"林青霞30", "柳岩,34", "張曼玉,35",“貂蟬,31", "王祖賢,33"};
●字符串數組中有多條信息, 請通過Predicate接口的拼裝將符合要求的字符串篩選到集合ArrayList中,並遍歷ArrayList集合
●同時滿足如下要求:姓名長度大於2;年齡大於33
●
分析
有兩個判斷條件,所以需要使用兩個Predicate接口,對條件進行判斷
必須同時滿足兩個條件,所以可以使用and方法連接兩個判斷條件
package com.Test01; /* String[] strArray = {"林青霞,30”,“柳岩,34", "張曼玉,35", "貂蟬,31","王祖賢,33"}; 字符串數組中有多條信息,請通過Predicate接口的拼裝將符合要求的字符串篩選到集合Arraylist中,並遍歷Arraylist集合 要求:同時滿足如下要求 1:姓名長度大於2 2:年齡大於33 分析: 1:有兩個判斷條件,所以需要使用兩個Predicate接口,對條件進行判斷 2:必須同時滿足兩個條件,所以可以使用and方法連接兩個判斷條件 */ import java.util.ArrayList; import java.util.function.Predicate; public class PredicateTest { public static void main(String[] args) { String[] strArray = {"林青霞,30", "柳岩,34", "張曼玉,35", "貂蟬,31", "王祖賢,33"}; ArrayList<String> stringArrayList = myfilter(strArray, s -> s.split(",")[0].length() > 2, s -> Integer.parseInt(s.split(",")[1]) > 33); for (String s : stringArrayList) { System.out.println(s); } } // 請通過Predicate接口的拼裝將符合要求的字符串篩選到集合ArrayList中, private static ArrayList<String> myfilter(String[] arr, Predicate<String> pre1, Predicate<String> pre2) { //定義一個集合 ArrayList<String> array = new ArrayList<String>(); for (String s : arr) { String name = s.split(",")[0]; int age = Integer.parseInt(s.split(",")[1]); if (pre1.and(pre2).test(s)) { array.add(s); } } return array; } }
4, Function接口
@FunctionalInterface
public interface Function<T,R>
Function<T,R>:常用的兩個方法
R apply(Tt):將此函數應用於給定的參數
default <V> Function andThen(Function after):返回-個組合函數,首先將該函數應用於輸入,然后將after函數應用於結果
Function<T,R>接口通常用於對參數進行處理,轉換(處理邏輯由Lambda表達式實現),然后返回一個新的值
package com.Test01; /* Function<T,R>:常用的兩個方法 R apply (T t):將此函數應用於給定的參數 default <V> Function andThen (Function after): 返回一個組合函數,首先將該函數應用於輸入,然后將ofter函數應用於結果 Function<T, R>接口通常用於對參數進行處理,轉換(處理邏輯由L ambda表達式實現),然后返回一一個新的值 */ import java.util.function.Function; public class FunctionDemo { public static void main(String[] args) { // Convert("100", (String s) -> { // return Integer.parseInt(s); // }); Convert("100", s -> Integer.parseInt(s)); Convert("100", Integer::parseInt); Convert(100, i-> String.valueOf(i+566)); Convert("300",s->Integer.parseInt(s),i->String.valueOf(i+300)); } //定義一個方法,把一個字符串轉換int類型,在控制台輸出 private static void Convert(String s, Function<String, Integer> fun) { // Integer i = fun.apply(s); int i = fun.apply(s); System.out.println(i); } //定義一個方法,把一個int類型的數據加上一個整數之后,轉為字符串在控制台輸出 private static void Convert(int i, Function<Integer, String> fun) { String s = fun.apply(i); System.out.println(s); } //定義一個方法,把一個字符串轉換int類型,把int類型的數據加上一一個整數之后, // 轉為字符串在控制台輸出 private static void Convert(String s,Function<String,Integer> fun1,Function<Integer,String> fun2) { // Integer i = fun1.apply(s); // String s1 = fun2.apply(i); // System.out.println(s1); String s1 = fun1.andThen(fun2).apply(s); System.out.println(s1); } }
練習
package com.Test01; /* ●Strings = "林青霞30"; ●請按照我指定的要求進行操作: 1:將字符串截取得到數字年齡部分string 2:將上一步的年齡字符串轉換成為int類型的數據int 3:將上一步的int數據加70,得到個int結果,在控制台輸出 ●請通過Function接口來實現函數拼接 */ import java.util.function.Function; public class FunctionDemo02 { public static void main(String[] args) { Convert("林青霞30",s-> Integer.parseInt(s.substring(3,5))+70); //也可以按照題目的要求一步一步來 } private static void Convert(String s, Function<String, Integer> fun) { Integer i = fun.apply(s); System.out.println(i); } }