1 函数式接口概述【理解】
概念
有且仅有一个抽象方法的接口
如何检测一个接口是不是函数式接口
@FunctionalInterface
放在接口定义的上方:如果接口是函数式接口,编译通过;如果不是,编译失败
注意事项
我们自己定义函数式接口的时候, @FunctionalInterface 是可选的,就算我不写这个注解,只要保证满足函数
式接口定义的条件,也照样是函数式接口。但是,建议加上该注解
2 函数式接口作为方法的参数【应用】
需求描述
定义一个类 (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 () + " 线程启动了 " ); } }); //Lambda 方式 startThread (() -> System . out . println ( Thread . currentThread (). getName () + " 线 程启动了 " )); } private static void startThread ( Runnable r ) { new Thread ( r ). start (); } }
3 函数式接口作为方法的返回值【应用】
需求描述
定义一个类 (ComparatorDemo) ,在类中提供两个方法
一个方法是: Comparator getComparator() 方法返回值 Comparator 是一个函数式接口
一个方法是主方法,在主方法中调用 getComparator 方法
代码演示
4 常用函数式接口之Supplier【应用】
Supplier 接口
Supplier 接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的 get 方法就会生产
什么类型的数据供我们使用。
常用方法
只有一个无参的方法
public class ComparatorDemo { public static void main ( String [] args ) { // 定义集合,存储字符串元素 ArrayList < String > array = new ArrayList < String > (); array . add ( "cccc" ); array . add ( "aa" ); array . add ( "b" ); array . add ( "ddd" ); System . out . println ( " 排序前: " + array ); Collections . sort ( array , getComparator ()); System . out . println ( " 排序后: " + array ); } private static Comparator < String > getComparator () { // 匿名内部类的方式实现 // return new Comparator<String>() { // @Override // public int compare(String s1, String s2) { // return s1.length()-s2.length(); // } // }; //Lambda 方式实现 return ( s1 , s2 ) -> s1 . length () - s2 . length (); }
} 方法名
说明
T get()
按照某种实现逻辑 ( 由 Lambda 表达式实现 ) 返回一个数据
代码演示
5 Supplier接口练习之获取最大值【应用】
案例需求
定义一个类 (SupplierTest) ,在类中提供两个方法
一个方法是: int getMax(Supplier sup) 用于返回一个 int 数组中的最大值
一个方法是主方法,在主方法中调用 getMax 方法
示例代码
public class SupplierDemo { public static void main ( String [] args ) { String s = getString (() -> " 林青霞 " ); System . out . println ( s ); Integer i = getInteger (() -> 30 ); System . out . println ( i ); } // 定义一个方法,返回一个整数数据 private static Integer getInteger ( Supplier < Integer > sup ) { return sup . get (); } // 定义一个方法,返回一个字符串数据 private static String getString ( Supplier < String > sup ) { return sup . get (); } } public class SupplierTest { public static void main ( String [] args ) { // 定义一个 int 数组 int [] arr = { 19 , 50 , 28 , 37 , 46 }; int maxValue = getMax (() -> { int max = arr [ 0 ]; for ( int i = 1 ; i < arr . length ; i ++ ) { if ( arr [ i ] > max ) { max = arr [ i ]; } }
6 常用函数式接口之Consumer【应用】
Consumer 接口
Consumer 接口也被称为消费型接口,它消费的数据的数据类型由泛型指定
方法名
说明
void accept(T t)
对给定的参数执行此操作
default Consumer andThen(Consumer
after)
返回一个组合的 Consumer ,依次执行此操作,然后执行
after 操作
常用方法
Consumer :包含两个方法
代码演示
return max ; }); System . out . println ( maxValue ); } // 返回一个 int 数组中的最大值 private static int getMax ( Supplier < Integer > sup ) { return sup . get (); } } public class ConsumerDemo { public static void main ( String [] args ) { // 操作一 operatorString ( " 林青霞 " , s -> System . out . println ( s )); // 操作二 operatorString ( " 林青霞 " , s -> System . out . println ( new StringBuilder ( s ). reverse (). toString ())); System . out . println ( "--------" ); // 传入两个操作使用 andThen 完成 operatorString ( " 林青霞 " , s -> System . out . println ( s ), s -> System . out . println ( new StringBuilder ( s ). reverse (). toString ())); } // 定义一个方法,用不同的方式消费同一个字符串数据两次 private static void operatorString ( String name , Consumer < String > con1 , Consumer < String > con2 ) { // con1.accept(name); // con2.accept(name); con1 . andThen ( con2 ). accept ( name ); }
7 Consumer接口练习之按要求打印信息【应用】
案例需求
String[] strArray = {" 林青霞 ,30", " 张曼玉 ,35", " 王祖贤 ,33"};
字符串数组中有多条信息,请按照格式: “ 姓名: XX, 年龄: XX" 的格式将信息打印出来
要求:
把打印姓名的动作作为第一个 Consumer 接口的 Lambda 实例
把打印年龄的动作作为第二个 Consumer 接口的 Lambda 实例
将两个 Consumer 接口按照顺序组合到一起使用
示例代码
8 常用函数式接口之Predicate【应用】
Predicate 接口
Predicate 接口通常用于判断参数是否满足指定的条件
常用方法
// 定义一个方法,消费一个字符串数据 private static void operatorString ( String name , Consumer < String > con ) { con . accept ( name ); } } public class ConsumerTest { public static void main ( String [] args ) { String [] strArray = { " 林青霞 ,30" , " 张曼玉 ,35" , " 王祖贤 ,33" }; printInfo ( strArray , str -> System . out . print ( " 姓名: " + str . split ( "," )[ 0 ]), str -> System . out . println ( ", 年龄: " + Integer . parseInt ( str . split ( "," )[ 1 ]))); } private static void printInfo ( String [] strArray , Consumer < String > con1 , Consumer < String > con2 ) { for ( String str : strArray ) { con1 . andThen ( con2 ). accept ( str ); } }
} 方法名
说明
boolean test(T t)
对给定的参数进行判断 ( 判断逻辑由 Lambda 表达式实现 ) ,返回
一个布尔值
default Predicate negate()
返回一个逻辑的否定,对应逻辑非
default Predicate and(Predicate
other)
返回一个组合判断,对应短路与
default Predicate or(Predicate
other)
返回一个组合判断,对应短路或
代码演示
public class PredicateDemo01 { 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 ); } // 判断给定的字符串是否满足要求 private static boolean checkString ( String s , Predicate < String > pre ) { // return !pre.test(s); return pre . negate (). test ( s ); } } 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 = checkString ( "hello" , s -> s . length () > 8 , s -> s . length () < 15 ); System . out . println ( b3 ); boolean b4 = checkString ( "helloworld" , s -> s . length () > 8 , s -> s . length () < 15 ); System . out . println ( b4 ); } // 同一个字符串给出两个不同的判断条件,最后把这两个判断的结果做逻辑与运算的结果作为最终的结果 private static boolean checkString ( String s , Predicate < String > pre1 , Predicate < String > pre2 ) { return pre1 . or ( pre2 ). test ( s ); }
9 Predicate接口练习之筛选满足条件数据【应用】
练习描述
String[] strArray = {" 林青霞 ,30", " 柳岩 ,34", " 张曼玉 ,35", " 貂蝉 ,31", " 王祖贤 ,33"};
字符串数组中有多条信息,请通过 Predicate 接口的拼装将符合要求的字符串筛选到集合 ArrayList 中,并
遍历 ArrayList 集合
同时满足如下要求:姓名长度大于 2 ;年龄大于 33
分析
有两个判断条件 , 所以需要使用两个 Predicate 接口 , 对条件进行判断
必须同时满足两个条件 , 所以可以使用 and 方法连接两个判断条件
示例代码
// 判断给定的字符串是否满足要求 private static boolean checkString ( String s , Predicate < String > pre ) { return pre . test ( s ); } } public class PredicateTest { public static void main ( String [] args ) { String [] strArray = { " 林青霞 ,30" , " 柳岩 ,34" , " 张曼玉 ,35" , " 貂蝉 ,31" , " 王祖 贤 ,33" }; ArrayList < String > array = myFilter ( strArray , s -> s . split ( "," )[ 0 ]. length () > 2 , s -> Integer . parseInt ( s . split ( "," )[ 1 ]) > 33 ); for ( String str : array ) { System . out . println ( str ); } } // 通过 Predicate 接口的拼装将符合要求的字符串筛选到集合 ArrayList 中 private static ArrayList < String > myFilter ( String [] strArray , Predicate < String > pre1 , Predicate < String > pre2 ) { // 定义一个集合 ArrayList < String > array = new ArrayList < String > (); // 遍历数组 for ( String str : strArray ) { if ( pre1 . and ( pre2 ). test ( str )) { array . add ( str ); } } return array ; } }
10 常用函数式接口之Function【应用】
Function 接口
Function<T,R> 接口通常用于对参数进行处理,转换 ( 处理逻辑由 Lambda 表达式实现 ) ,然后返回一个新的值
方法名
说明
R apply(T t)
将此函数应用于给定的参数
default Function
andThen(Function after)
返回一个组合函数,首先将该函数应用于输入,然后将 after 函
数应用于结果
常用方法
代码演示
public class FunctionDemo { public static void main ( String [] args ) { // 操作一 convert ( "100" , s -> Integer . parseInt ( s )); // 操作二 convert ( 100 , i -> String . valueOf ( i + 566 )); // 使用 andThen 的方式连续执行两个操作 convert ( "100" , s -> Integer . parseInt ( s ), i -> String . valueOf ( i + 566 )); } // 定义一个方法,把一个字符串转换 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 ) { String ss = fun1 . andThen ( fun2 ). apply ( s ); System . out . println ( ss ); }
}
11 Function接口练习之按照指定要求操作数据【应用】
练习描述
String s = " 林青霞 ,30";
请按照我指定的要求进行操作:
1: 将字符串截取得到数字年龄部分
2: 将上一步的年龄字符串转换成为 int 类型的数据
3: 将上一步的 int 数据加 70 ,得到一个 int 结果,在控制台输出
请通过 Function 接口来实现函数拼接
示例代码
public class FunctionTest { public static void main ( String [] args ) { String s = " 林青霞 ,30" ; convert ( s , ss -> ss . split ( "," )[ 1 ], Integer :: parseInt , i -> i + 70 ); } private static void convert ( String s , Function < String , String > fun1 , Function < String , Integer > fun2 , Function < Integer , Integer > fun3 ) { int i = fun1 . andThen ( fun2 ). andThen ( fun3 ). apply ( s ); System . out . println ( i ); } }