1.定义
函数式接口简单的来说就是使用'@FunctionalInterface'注解并且只包含一个抽象方法的接口
2.示例
jdk中的Runnable就是一个函数式接口,它的签名如下:
我们在使用时的声明初始化如下:
接下来,自定义一个函数式接口:
@FunctionalInterface
public interface MyFunctionalInterface {
void method();
}
它的声明初始化如下:
MyFunctionalInterface myFunctionalInterface = new MyFunctionalInterface() {
@Override
public void method() {
System.out.println("这是自定义的一个函数式接口");
}
};
MyFunctionalInterface myFunctionalInterface2 = () -> {
System.out.println("这是自定义函数式接口的简化初始化方式");
};
3.jdk中的一些函数式接口
3.1.Consumer<T>
消费型的接口
它的签名如下:
简单示例如下:
1.首先定义一个形参为Consumer的方法
void testConsumer(Consumer<String> consumer,String arg){
consumer.accept(arg);
}
2.调用
//第一种调用
testConsumer(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s+"1");
}
}, "aaa");
//第二种调用(简化)
testConsumer(arg-> System.out.println(arg+"2"),"bbb");
在调用中下面是上面的简化写法(首先要明确的是函数式接口可以作为函数的实参进行传递,因此有了上面的写法),简化是根据函数式接口中的抽象方法来简化的,只有一个参数,就写一个参数名,然后->,如果抽象方法的实现只有一行代码可以不写大括号和return
3.andThen(Consumer<? extents T> after)解析
andThen方法的形参是Consumer函数式接口,返回一个Consumer对象,因此可以连续使用n个andThen方法,每一次调用内部执行了对应andThen方法中consumer形参的accept方法.
具体的简单示例如下:
void testConsumer(Consumer<String> consumer,Consumer<String> consumer2,Consumer<String> consumer3,String arg){
consumer.andThen(consumer2).andThen(consumer3).accept(arg);
}
void testConsumer2(Consumer<Integer> consumer,int a){
consumer.andThen(consumer).andThen(consumer).accept(a);
}
testConsumer(arg-> System.out.println(arg+"1"),a-> System.out.println(a+"2"),a-> System.out.println(a+"3"),"bbb");
testConsumer2(a->{
a++;
System.out.println(a);
},1);
需要注意的是函数式接口Consumer中的accept方法的返回值是void的,因此不会产生重复调用的结果累加,每次andThen中的操作都是对最原始数据的一种消费.
3.2.Supplier<T>
供给型接口,无传入参数,生产一个指定泛型类型的数据
它的定义如下:
简单示例如下:
1.首先定义一个形参为Supplier的函数
这里说明一点,在定义函数的时候可以指定泛型,并在Supplier处引用该泛型Supplier<T> supplier,这样使得程序的多态性更加的丰富
int[] testSupplier(Supplier<Integer> supplier,int length){
int[] nums = new int[length];
for (int i = 0; i < length; i++) {
nums[i] = supplier.get();
}
return nums;
}
2.调用
final int[] ints = testSupplier(new Supplier<Integer>() {
@Override
public Integer get() {
return new Random().nextInt(100);
}
}, 10);
System.out.println(Arrays.toString(ints));
//是上面的简化写法,只有一行代码的时候,可以不用写return
final int[] ints1 = testSupplier(() -> new Random().nextInt(200), 10);
System.out.println(Arrays.toString(ints1));
3.3Function<T,R>
转换型接口,它的抽象方法apply传入一个T类型的参数,返回一个R类型的结果
它的签名如下:
1.定义一个形参为Function的函数
Integer testFunction(Function<String,Integer> function,String str){
return function.apply(str);
}
2.调用
final Integer integer = testFunction((String a) -> Integer.parseInt(a), "12");
System.out.println(integer.intValue());
方法compose,andthen解析(待完成)
4.Predicate<T>
断言型函数式接口,抽象方法test(T t)接口一个参数,判断该参数是否符合某种规则,符合为true,不符合为false,用于过滤
它的签名如下:
1.定义一个形参为Predicate的方法
//传入一个list集合
static List<String> testPredicate(Predicate<String> predicate,List<String> list){
List<String> newList = new LinkedList();
for (String s : list) {
if (predicate.test(s)) {
newList.add(s);
}
}
return newList;
}
2.调用
List<String> list = Arrays.asList("a","b","c","aa","bb","cc","dd");
final List<String> list1 = testPredicate(a -> a.length() > 1, list);
System.out.println(list1);
方法and,or,isEqual,not,negate解析(待完成)
总结:函数式结果总共分为四类,消费性(Consumer),供给型(Supplier),转换型(Function),断言型(Predicate),为了方便记忆,总结为下面的简短语 肯(Consumer)消费,私(Supplier)供给,发(Function)转换,皮(Predicate)断言
个人理解:这四种函数式接口都是定义了某个规则用于程序调用,所以可以不在方法形参处声明,可以在类中直接定义某种规则等其他的方式,用于后续的逻辑判断,示例如下:
class Rule{
public static final Function<String, Integer> function = new Function<>() {
@Override
public Integer apply(String str) {
return Integer.parseInt(str);
}
};
}
调用如下:
final Integer intResult = Rule.function.apply("12");
System.out.println(intResult);