一、函數式接口
1.什麼是函數式接口
接口中只有一個抽象方法(不包括默認、靜態)
2.如何去定義一個函數式接口
@FunctionalInterface 註解的作用:約束接口中只能有一個抽象方法
定義一個接口,提供一個抽象方法
3.Lambda表達式格式
(參數) 調用方法,傳遞參數
-> 將小括號中參數傳遞到大括號中
{} 實現代碼的方法體
4.通過Lambda表達式輸出D盤下所有的.txt文件的名稱
public class Demo01 {
public static void main(String[] args) {
File dir = new File("d:\\");
print(dir);
}
public static void print(File dir) {
File[] subFiles = dir.listFiles(pathname -> pathname.getName().endsWith(".txt") || pathname.isDirectory());
if(subFiles != null) {
for(File subFile : subFiles) {
if(subFile.isDirectory()) {
print(subFile);
}else {
System.out.println(subFile.getName());
}
}
}
}
}
5.Lambda延遲加載機制
//函數式接口
@FunctionalInterface
public interface MessageBuilder {
//定義一個拼接消息的抽象方法,返回被拼接的消息
public abstract String builderMessage();
}
//測試類
public class Demo02Lambda {
//定義一個顯示日誌的方法,方法的參數傳遞日誌的等級和MessageBuilder接口
public static void showLog(int level, MessageBuilder mb){
//對日誌的等級進行判斷,如果是1級,則調用MessageBuilder接口中的builderMessage方法
if(level==1){
System.out.println(mb.builderMessage());
}
}
public static void main(String[] args) {
//定義三個日誌信息
String msg1 = "Hello";
String msg2 = "World";
String msg3 = "Java";
//調用showLog方法,參數MessageBuilder是一個函數式接口,所以可以傳遞Lambda表達式
/*showLog(2,()->{
//返回一個拼接好的字符串
return msg1+msg2+msg3;
});*/
/*
使用Lambda表達式作爲參數傳遞,僅僅是把參數傳遞到showLog方法中
只有滿足條件,日誌的等級是1級
纔會調用接口MessageBuilder中的方法builderMessage
纔會進行字符串的拼接
如果條件不滿足,日誌的等級不是1級
那麼MessageBuilder接口中的方法builderMessage也不會執行
所以拼接字符串的代碼也不會執行
所以不會存在性能的浪費
*/
showLog(2,()->{
System.out.println("不滿足條件不執行");
//返回一個拼接好的字符串
return msg1+msg2+msg3;
});
}
}
6.函數式接口作爲方法的參數
public class Demo01Runnable {
//定義一個方法startThread,方法的參數使用函數式接口Runnable
public static void startThread(Runnable run){
//開啓多線程
new Thread(run).start();
}
public static void main(String[] args) {
//調用startThread方法,方法的參數是一個接口,那麼我們可以傳遞這個接口的匿名內部類
startThread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-->"+"線程啓動了");
}
});
//調用startThread方法,方法的參數是一個函數式接口,所以可以傳遞Lambda表達式
startThread(()->{
System.out.println(Thread.currentThread().getName()+"-->"+"線程啓動了");
});
//優化Lambda表達式
startThread(()->System.out.println(Thread.currentThread().getName()+"-->"+"線程啓動了"));
}
}
7.函數式接口作爲方法的返回值類型
public class Demo02Comparator {
//定義一個方法,方法的返回值類型使用函數式接口Comparator
public static Comparator<String> getComparator(){
//方法的返回值類型是一個接口,那麼我們可以返回這個接口的匿名內部類
/*return new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
//按照字符串的降序排序
return o2.length()-o1.length();
}
};*/
//方法的返回值類型是一個函數式接口,所有我們可以返回一個Lambda表達式
/*return (String o1, String o2)->{
//按照字符串的降序排序
return o2.length()-o1.length();
};*/
//繼續優化Lambda表達式
return (o1, o2)->o2.length()-o1.length();
}
public static void main(String[] args) {
//創建一個字符串數組
String[] arr = {"aaa","b","cccccc","dddddddddddd"};
//輸出排序前的數組
System.out.println(Arrays.toString(arr));//[aaa, b, cccccc, dddddddddddd]
//調用Arrays中的sort方法,對字符串數組進行排序
Arrays.sort(arr,getComparator());
//輸出排序後的數組
System.out.println(Arrays.toString(arr));//[dddddddddddd, cccccc, aaa, b]
}
}
二、常用的函數式接口
1.Supplier<T>函數式接口-用來做生產的
T get();
示例代碼:
public class Demo01Supplier {
//定義一個方法,方法的參數傳遞Supplier<T>接口,泛型執行String,get方法就會返回一個String
public static String getString(Supplier<String> sup){
return sup.get();
}
public static void main(String[] args) {
//調用getString方法,方法的參數Supplier是一個函數式接口,所以可以傳遞Lambda表達式
String s = getString(()->{
//生產一個字符串,並返回
return "胡歌";
});
System.out.println(s);
//優化Lambda表達式
String s2 = getString(()->"胡歌");
System.out.println(s2);
}
}
使用Supplier接口中的get方法。來獲取數組中的最大值
public class Demo02Test {
//定義一個方法,用於獲取int類型數組中元素的最大值,方法的參數傳遞Supplier接口,泛型使用Integer
public static int getMax(Supplier<Integer> sup){
return sup.get();
}
public static void main(String[] args) {
//定義一個int類型的數組,並賦值
int[] arr = {100,0,-50,880,99,33,-30};
//調用getMax方法,方法的參數Supplier是一個函數式接口,所以可以傳遞Lambda表達式
int maxValue = getMax(()->{
//獲取數組的最大值,並返回
//定義一個變量,把數組中的第一個元素賦值給該變量,記錄數組中元素的最大值
int max = arr[0];
//遍歷數組,獲取數組中的其他元素
for (int i : arr) {
//使用其他的元素和最大值比較
if(i>max){
//如果i大於max,則替換max作爲最大值
max = i;
}
}
//返回最大值
return max;
});
System.out.println("數組中元素的最大值是:"+maxValue);
}
}
2.Consumer<T t>函數式接口-用來做消費的
void accept(T t);
示例代碼:
public class Demo01Consumer {
/*
定義一個方法
方法的參數傳遞一個字符串的姓名
方法的參數傳遞Consumer接口,泛型使用String
可以使用Consumer接口消費字符串的姓名
*/
public static void method(String name, Consumer<String> con){
con.accept(name);
}
public static void main(String[] args) {
//調用method方法,傳遞字符串姓名,方法的另一個參數是Consumer接口,是一個函數式接口,所以可以傳遞Lambda表達式
method("趙麗穎",(String name)->{
//對傳遞的字符串進行消費
//消費方式:直接輸出字符串
//System.out.println(name);
//消費方式:把字符串進行反轉輸出
String reName = new StringBuffer(name).reverse().toString();
System.out.println(reName);
});
}
}
andThen(Consumer<T t>);
示例代碼:
public class Demo02AndThen {
//定義一個方法,方法的參數傳遞一個字符串和兩個Consumer接口,Consumer接口的泛型使用字符串
public static void method(String s, Consumer<String> con1, Consumer<String> con2){
//con1.accept(s);
//con2.accept(s);
//使用andThen方法,把兩個Consumer接口連接到一起,在消費數據
con1.andThen(con2).accept(s);//con1連接con2,先執行con1消費數據,在執行con2消費數據
}
public static void main(String[] args) {
//調用method方法,傳遞一個字符串,兩個Lambda表達式
method("Hello",
(t)->{
//消費方式:把字符串轉換爲大寫輸出
System.out.println(t.toUpperCase());
},
(t)->{
//消費方式:把字符串轉換爲小寫輸出
System.out.println(t.toLowerCase());
});
}
}
字符串拼接案例
public class Demo03Test {
//定義一個方法,參數傳遞String類型的數組和兩個Consumer接口,泛型使用String
public static void printInfo(String[] arr, Consumer<String> con1,Consumer<String> con2){
//遍歷字符串數組
for (String message : arr) {
//使用andThen方法連接兩個Consumer接口,消費字符串
con1.andThen(con2).accept(message);
/*con1.accept(message);
con2.accept(message);*/
}
}
public static void main(String[] args) {
//定義一個字符串類型的數組
String[] arr = { "迪麗熱巴,女", "古力娜扎,女", "馬爾扎哈,男" };
//調用printInfo方法,傳遞一個字符串數組,和兩個Lambda表達式
printInfo(arr,(message)->{
//消費方式:對message進行切割,獲取姓名,按照指定的格式輸出
String name = message.split(",")[0];
System.out.print("姓名: "+name);
},(message)->{
//消費方式:對message進行切割,獲取年齡,按照指定的格式輸出
String sex = message.split(",")[1];
System.out.println("。性別: "+sex+"。");
});
}
}
3.Predicate<T>函數式接口
boolean test(T t); 獲取布爾類型結果
示例代碼:
public class Demo01Predicate {
/*
定義一個方法
參數傳遞一個String類型的字符串
傳遞一個Predicate接口,泛型使用String
使用Predicate中的方法test對字符串進行判斷,並把判斷的結果返回
*/
public static boolean checkString(String s, Predicate<String> pre){
return pre.test(s);
}
public static void main(String[] args) {
//定義一個字符串
String s = "abcdef";
//調用checkString方法對字符串進行校驗,參數傳遞字符串和Lambda表達式
/*boolean b = checkString(s,(String str)->{
//對參數傳遞的字符串進行判斷,判斷字符串的長度是否大於5,並把判斷的結果返回
return str.length()>5;
});*/
//優化Lambda表達式
boolean b = checkString(s,str->str.length()>5);
System.out.println(b);
}
}
and(); 代表&&的意思
示例代碼:
public class Demo02Predicate_and {
/*
定義一個方法,方法的參數,傳遞一個字符串
傳遞兩個Predicate接口
一個用於判斷字符串的長度是否大於5
一個用於判斷字符串中是否包含a
兩個條件必須同時滿足
*/
public static boolean checkString(String s, Predicate<String> pre1,Predicate<String> pre2){
//return pre1.test(s) && pre2.test(s);
return pre1.and(pre2).test(s);//等價於return pre1.test(s) && pre2.test(s);
}
public static void main(String[] args) {
//定義一個字符串
String s = "abcdef";
//調用checkString方法,參數傳遞字符串和兩個Lambda表達式
boolean b = checkString(s,(String str)->{
//判斷字符串的長度是否大於5
return str.length()>5;
},(String str)->{
//判斷字符串中是否包含a
return str.contains("a");
});
System.out.println(b);
}
}
or(); 代表||的意思
示例代碼:
public class Demo03Predicate_or {
/*
定義一個方法,方法的參數,傳遞一個字符串
傳遞兩個Predicate接口
一個用於判斷字符串的長度是否大於5
一個用於判斷字符串中是否包含a
滿足一個條件即可
*/
public static boolean checkString(String s, Predicate<String> pre1, Predicate<String> pre2){
//return pre1.test(s) || pre2.test(s);
return pre1.or(pre2).test(s);//等價於return pre1.test(s) || pre2.test(s);
}
public static void main(String[] args) {
//定義一個字符串
String s = "bc";
//調用checkString方法,參數傳遞字符串和兩個Lambda表達式
boolean b = checkString(s,(String str)->{
//判斷字符串的長度是否大於5
return str.length()>5;
},(String str)->{
//判斷字符串中是否包含a
return str.contains("a");
});
System.out.println(b);
}
}
negate(); 代表的是取反
示例代碼:
public class Demo04Predicate_negate {
/*
定義一個方法,方法的參數,傳遞一個字符串
使用Predicate接口判斷字符串的長度是否大於5
*/
public static boolean checkString(String s, Predicate<String> pre){
//return !pre.test(s);
return pre.negate().test(s);//等效於return !pre.test(s);
}
public static void main(String[] args) {
//定義一個字符串
String s = "abc";
//調用checkString方法,參數傳遞字符串和Lambda表達式
boolean b = checkString(s,(String str)->{
//判斷字符串的長度是否大於5,並返回結果
return str.length()>5;
});
System.out.println(b);
}
}
案例-將滿足條件的字符串保存到集合中
public class Demo05Test {
/*
定義一個方法
方法的參數傳遞一個包含人員信息的數組
傳遞兩個Predicate接口,用於對數組中的信息進行過濾
把滿足條件的信息存到ArrayList集合中並返回
*/
public static ArrayList<String> filter(String[] arr,Predicate<String> pre1,Predicate<String> pre2){
//定義一個ArrayList集合,存儲過濾之後的信息
ArrayList<String> list = new ArrayList<>();
//遍歷數組,獲取數組中的每一條信息
for (String s : arr) {
//使用Predicate接口中的方法test對獲取到的字符串進行判斷
boolean b = pre1.and(pre2).test(s);
//對得到的布爾值進行判斷
if(b){
//條件成立,兩個條件都滿足,把信息存儲到ArrayList集合中
list.add(s);
}
}
//把集合返回
return list;
}
public static void main(String[] args) {
//定義一個儲存字符串的數組
String[] array = { "迪麗熱巴,女", "古力娜扎,女", "馬爾扎哈,男", "趙麗穎,女" };
//調用filter方法,傳遞字符串數組和兩個Lambda表達式
ArrayList<String> list = filter(array,(String s)->{
//獲取字符串中的性別,判斷是否爲女
return s.split(",")[1].equals("女");
},(String s)->{
//獲取字符串中的姓名,判斷長度是否爲4個字符
return s.split(",")[0].length()==4;
});
//遍歷集合
for (String s : list) {
System.out.println(s);
}
}
}
4.Function<T t,R r>函數式接口
R apply(T t); 數據類型轉換
public class Demo01Function {
/*
定義一個方法
方法的參數傳遞一個字符串類型的整數
方法的參數傳遞一個Function接口,泛型使用<String,Integer>
使用Function接口中的方法apply,把字符串類型的整數,轉換爲Integer類型的整數
*/
public static void change(String s, Function<String,Integer> fun){
//Integer in = fun.apply(s);
int in = fun.apply(s);//自動拆箱 Integer->int
System.out.println(in);
}
public static void main(String[] args) {
//定義一個字符串類型的整數
String s = "1234";
//調用change方法,傳遞字符串類型的整數,和Lambda表達式
change(s,(String str)->{
//把字符串類型的整數,轉換爲Integer類型的整數返回
return Integer.parseInt(str);
});
//優化Lambda
change(s,str->Integer.parseInt(str));
}
}
andThen(Function<T t,R r>);
示例代碼:
public class Demo02Function_andThen {
/*
定義一個方法
參數串一個字符串類型的整數
參數再傳遞兩個Function接口
一個泛型使用Function<String,Integer>
一個泛型使用Function<Integer,String>
*/
public static void change(String s, Function<String,Integer> fun1,Function<Integer,String> fun2){
String ss = fun1.andThen(fun2).apply(s);
System.out.println(ss);
}
public static void main(String[] args) {
//定義一個字符串類型的整數
String s = "123";
//調用change方法,傳遞字符串和兩個Lambda表達式
change(s,(String str)->{
//把字符串轉換爲整數+10
return Integer.parseInt(str)+10;
},(Integer i)->{
//把整數轉換爲字符串
return i+"";
});
//優化Lambda表達式
change(s,str->Integer.parseInt(str)+10,i->i+"");
}
}
Function接口的案例
public class Demo03Test {
/*
定義一個方法
參數傳遞包含姓名和年齡的字符串
參數再傳遞3個Function接口用於類型轉換
*/
public static int change(String s, Function<String,String> fun1,
Function<String,Integer> fun2,Function<Integer,Integer> fun3){
//使用andThen方法把三個轉換組合到一起
return fun1.andThen(fun2).andThen(fun3).apply(s);
}
public static void main(String[] args) {
//定義一個字符串
String str = "趙麗穎,20";
//調用change方法,參數傳遞字符串和3個Lambda表達式
int num = change(str,(String s)->{
//"趙麗穎,20"->"20"
return s.split(",")[1];
},(String s)->{
//"20"->20
return Integer.parseInt(s);
},(Integer i)->{
//20->120
return i+100;
});
System.out.println(num);
}
}
函數式接口、Lambda表達式(Consumer、Supplier、Function、Predicate)【總結】
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.