函数式接口
函数式接口:有且仅有一个抽象方法得接口
java中的函数式编程体现就是lamada表达式,所以函数式接口就是可以适用于lamada使用得接口,只有确保接口中有且仅有一个抽象方法,java中得lamada才能顺利进行推导
在接口中加上注释:@FunctionalInterface,如果接口时函数式接口,编译通过,如果不是,编译失败
函数式接口作为方法的参数
定义一个类RunnableDemo,在类中提供两个方法
一个方法是,startThread(Runnable r),方法参数Runnable是一个函数式接口
另一个方法是主方法,在主方法中调用startThread方法
public class RunnableDemo {
//ctrl b跟进看源码
public static void startThread(Runnable r){
Thread t = new Thread(r);
t.start();
}
public static void main(String[] args){
// 匿名内部类 Runnable是一个函数式接口
startThread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"启动");
}
});
startThread(()-> System.out.println(Thread.currentThread().getName()));
}
}
如果方法的参数是一个函数式接口,我们可以使用lamada表达式作为参数传递
函数式接口作为方法的返回值
定义一个类(ComparatorDemo),在类中提供两个方法
一个方法是:Comparator getCommparator() 方法返回值Comparator是一个函数式接口
一个方法是主方法,在主方法中调用getComparator方法
public class ComparatorDemo {
private static Comparator<String> getCommparator(){
//匿名内部类的方式实现
// Comparator<String> comp = new Comparator<String>() {
// @Override
// public int compare(String o1, String o2) {
// return o1.length()-o2.length();
// }
// }
// return new Comparator<String>() {
// @Override
// //按照长度排序
// public int compare(String o1, String o2) {
// return o1.length()-o2.length();
// }
// };
//lamada表达式
// return ((String o1,String o2) ->{
// return o1.length()-o2.length();
// });
return (o1,o2) -> o1.length()-o2.length();
}
public static void main(String[] args){
//构造使用场景
//定义集合,存储字符串元素
ArrayList<String> array = new ArrayList<String>();
array.add("sss");
array.add("b");
System.out.println(array);
Collections.sort(array,getCommparator());
System.out.println(array);
}
}
如果方法的返回值是一个函数式接口,我们可以使用lamada表达式作为结果返回
常用的函数式接口
java.util.function包下与定义了大量的皆苦
supplier接口
Supplier:包含一个无参的方法
T get():获得结果
该方法不需要参数,它会按照某种实现逻辑(有lamada表达式实现)返回一个数据
Supplier接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会产生什么类型的数据供我们使用
练习
定义一个类(SupplierTest),在类中提供两个方法
一个方法是int getMax(Supplier sup)用于返回int数组中的最大值
一个方法是主方法,在主方法中调用getMax方法
public class SupplierTest {
private static int getMax(Supplier<Integer> sup){
return sup.get();
}
public static void main(String[] args){
//定义一i个int数组
int[] arr = {19,23,4,5,78};
int maxValue = getMax(()->{
int max = arr[0];
for(int i=1; i<arr.length; i++){
if(arr[i] > max){
max = arr[i];
}
}
return max;
});
System.out.println(maxValue);
}
}
Consumer接口
-
-
Modifier and Type 方法 描述 void
accept(T t)
对给定的参数执行此操作。 default Consumer<T>
andThen(Consumer<? super T> after)
返回一个组成的 Consumer
,依次执行此操作,然后执行after
操作。
-
Comsumer接口也被称为消费型接口,它消费的数据的数据类型有泛型指定
public class ComsumerDemo {
public static void main(String[] args){
// opertorString("嗡嗡嗡",(String s)->{
// System.out.println(s);
// });
opertorString("嗡嗡嗡",s->System.out.println(s));
//方法引用
opertorString("嗡嗡嗡",System.out::println);
opertorString("w嗡嗡嗡",s->{
System.out.println(new StringBuilder(s).reverse().toString());
});
opertorString("日日日",s-> System.out.println(new StringBuilder(s).reverse().toString()));
opertorString("小问题",s->System.out.println(s),s-> {
System.out.println(new StringBuilder(s).reverse().toString());
});
}
//用不同的方式消费同一个字符串数据两次
private static void opertorString(String name,Consumer<String> con1,Consumer<String> con2){
// con1.accept(name);
// con2.accept(name);
//andThen相当于执行了两次after操作
con1.andThen(con2).accept(name);
}
//消费一个字符串数据
private static void opertorString(String name, Consumer<String> con){
con.accept(name);
}
}
练习
String[] strArray = {“小甘,80”,“小棠,56”,“小米,88”};
字符串数组中有多条信息,按照格式将信息打印出来
把打印姓名的动作作为第一个Consumer接口的lamada实例
把打印年龄的动作作为第二个consumer接口的lamada实例
将两个consumer接口按照顺序组合到一起使用
public class ConsumerDemo2 {
public static void main(String[] args){
String[] strArray = {"小甘,80", "小棠,56", "小米,88"};
printInfo(strArray,str->{
String name = str.split(",")[0];
System.out.println(name);
},str->{
int age = Integer.parseInt(str.split(",")[1]);
System.out.println(age);
});
}
private static void printInfo(String[] strArray , Consumer<String> con1,Consumer<String> con2){
for(String str:strArray){
con1.andThen(con2).accept(str);
}
}
}
Predicate接口
-
-
Modifier and Type 方法 描述 default Predicate<T>
and(Predicate<? super T> other)
返回一个组合的谓词,表示该谓词与另一个谓词的短路逻辑AND。 static <T> Predicate<T>
isEqual(Object targetRef)
返回一个谓词,根据 Objects.equals(Object, Object)
测试两个参数是否相等。default Predicate<T>
negate()
返回表示此谓词的逻辑否定的谓词。 default Predicate<T>
or(Predicate<? super T> other)
返回一个组合的谓词,表示该谓词与另一个谓词的短路逻辑或。 boolean
test(T t)
在给定的参数上评估这个谓词。
-
-
public interface Predicate<T>
表示一个参数的谓词(布尔值函数)。
public class PredicateDemo2 {
public static void main(String[] args){
boolean b1 = checkString("hello",s->s.length() > 8);
System.out.println(b1);
boolean b2 = checkString("helloyutrew",s->s.length() > 8);
System.out.println(b2);
boolean b3 = checkString("hello",s->s.length() > 8,s->s.length()<15);
System.out.println(b3);
}
//同一个字符串给出两种不同的判断条件按,最后把这两个判断的结果做逻辑与运算作为最后的结果
private 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.or(pre2).test(s);
}
//判断字符串是否满足要求
private static boolean checkString(String s, Predicate<String> pre){
return pre.test(s);
}
}
练习
String[] strArray = {“小甘,80”,“小棠,56”,“小米,88”};
字符串数组中有多条信息,请通过Predicate接口的拼装将符合要求的字符除按筛选到集合ArrayList中,并遍历ArrayList集合要求,同时满足下列要求:姓名长度大于2,年龄大于33
public class PredicateTest {
public static void main(String[] args){
String[] strArray = {"小甘,80","小棠,56","小米,88"};
ArrayList<String> array=myFilter(strArray,s-> s.split(",")[0].length() > 1,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;
}
}
Function接口
-
-
Modifier and Type 方法 描述 default <V> Function<T,V>
andThen(Function<? super R,? extends V> after)
返回一个组合函数,首先将该函数应用于其输入,然后将 after
函数应用于结果。R
apply(T t)
将此函数应用于给定的参数。 default <V> Function<V,R>
compose(Function<? super V,? extends T> before)
返回一个组合函数,首先将 before
函数应用于其输入,然后将此函数应用于结果。static <T> Function<T,T>
identity()
返回一个总是返回其输入参数的函数。
-
-
@FunctionalInterface public interface Function<T,R>
表示接受一个参数并产生结果的函数。
public class FunctionDemo {
public static void main(String[] args){
convert("100",s->Integer.parseInt(s));
//方法调用
convert("100",Integer::parseInt);
convert(100,i->String.valueOf(i + 556));
convert("100",s->Integer.parseInt(s),i->String.valueOf(i+988));
}
//定义一个方法,把一个字符串转换int类型,在控制台输出
private static void convert(String s, Function<String,Integer> fun){
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(i);
}
//定义一个方法,把一个字符串转换int类型,把int类型的数据加上一个整数以后,转为字符串在控制台输出
private static void convert(String s,Function<String,Integer> fun1,Function<Integer,String> fun2){
// Integer i = fun1.apply(s);
// String ss = fun2.apply(i);
// System.out.println(ss);
//把第一个函数的结果当作第二个函数的参数
String ss =fun1.andThen(fun2).apply(s);
System.out.println(ss);
}
}
练习
String = “林夏琳,30”
将字符串截取得到数字年龄部分
将上一步的年龄字符串转换成为int类型的数据
将上一步的int数据加70,得到一个int结果,在控制台输出
通过哦function接口实现函数拼接
public class FunctionDemo2 {
// String = "林夏琳,30"
//
// 将字符串截取得到数字年龄部分
//
// 将上一步的年龄字符串转换成为int类型的数据
//
// 将上一步的int数据加70,得到一个int结果,在控制台输出
//
// 通过哦function接口实现函数拼接
public static void main(String[] args){
String s = "林夏琳,30";
convert(s,ss-> s.split(",")[1],
ss->Integer.parseInt(ss)
,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);
}
}