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); } }