函数式接口
@FunctionalInterface
jdk中的英文注解
- An informative annotation type used to indicate that an interface
- type declaration is intended to be a functional interface as
- defined by the Java Language Specification.
在Java中只要有接口@FunctionalInterface代表他是 一个函数式接口。
Conceptually, a functional interface has exactly one abstract - method. Since {@linkplain java.lang.reflect.Method#isDefault()
- default methods} have an implementation, they are not abstract. If
- an interface declares an abstract method overriding one of the
- public methods of {@code java.lang.Object}, that also does
- not count toward the interface’s abstract method count
- since any implementation of the interface will have an
- implementation from {@code java.lang.Object} or elsewhere.
1.这个接口有且只能由一个抽象方法
2.jdk8之后可以在接口中实现方法了,可以通过default声明进行实现,但是他们不归属于抽象方法行列中
3.像重写超级父类Object中的public方法也是不算是抽象方法
例子:
下面展示一些内联代码片
。
@FunctionalInterface
public interface MyInterface {
void test();
//其满足了复写父类的抽象方法,其也认为其只有一个抽象类
String toString();
}
@FunctionalInterface
public interface MyInterface {
void test();
//其满足了复写父类的抽象方法,其也认为其只有一个抽象类
String toString();
}
但是下面这个就会报错
@FunctionalInterface
public interface MyIntestfaceTest {
void test();
String myString();
}
@FunctionalInterface
public interface MyIntestfaceTest {
void test();
String myString();
}
报错信息:Multiple non-overriding abstract methods found in interface com.curry.jdk8.MyIntestfaceTest意思是有多个抽象方法。
However, the compiler will treat any interface meeting the * definition of a functional interface as a functional interface * regardless of whether or not a {@code FunctionalInterface} * annotation is present on the interface declaration.
4.在编译过程中如果不加@FunctionalInterface注解时,如果你的类符合函数式接口的要求,在编译时还是按照函数式接口编译。*
Note that instances of functional interfaces can be created with
- lambda expressions, method references, or constructor references.
5.函数式接口可以通过三种方式进行创建lambda表达式,方法引用、构造函数引用(这篇文章主要先通过lambda表达式,其他两种后续文章简绍)
jdk中几种比较常用的函数式接口
1.Consumer
其只有输入参数无返回值
应用:
下面展示一些 jdk中是如何使用的
。
/**
* @author curry
* @Date 2022/1/18 9:43
* @since 1.0.0
*/
public class LamdaTest1 {
public static void main(String[] args) {
System.out.println("开始了..................");
// System.out.println(System.getProperty("file.encoding"));
List<Integer> list = Arrays.asList(1,2,3,4,5,6);
//传统的迭代方式一
for(int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println("------------------");
//传统迭代方式二
for (Integer i : list) {
System.out.println(i);
}
System.out.println("----------------");
// 内部类迭代
list.forEach(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println(integer);
}
});
System.out.println("--------------------");
//lambda使用
list.forEach(i -> System.out.println(i));
System.out.println("--------------------");
//方法引用使用
list.forEach(System.out::println);
}
}
2.Function<T, R>,BiFunction<T, U, R>
既有参数又有返回值
改变之前java只是用于值进行传递,可以通过行为进行传递,将实际行为通过回调函数进行处理
下面展示一些 自己如何用代码
。
/**
* @author curry
* @Date 2022/1/19 10:24
* @since 1.0.0
*/
/*
函数式接口Function并不是只管值,还在意执行行为
*/
public class FunctionTest {
public static void main(String[] args) {
FunctionTest functionTest = new FunctionTest();
//传统的处理加,乘这种行为是提前已经写好了
System.out.println(functionTest.add(9));
System.out.println(functionTest.mul(9));
System.out.println("传统的调用方式");
//函数接口方式 是您实际要用的时候传递过去的
System.out.println(functionTest.compute(9,a->{return 2+a;}));
System.out.println(functionTest.compute(9,a->a*2));
System.out.println("高阶函数式调用方式");
}
//高阶函数 两个参数可以用BiFunction
public int compute(int a, Function<Integer,Integer> function) {
return function.apply(a);
}
public int add(int a) {
return a+2;
}
public int mul(int a){
return a*2;
}
}
实际jdk中哪里用到了,如:流stream中map()底层用到的就是Function
public class InterfaceObject {
public static void main(String[] args) {
List<String> list1 = Arrays.asList("lee","curry","lee_curry");
//stream map中有个函数式接口 用lambda处理
list1.stream().map(item -> item.toUpperCase()).forEach(item -> System.out.println(item));
//stream map中的函数式接口 用方法引用处理 stream中有fileter(Predicate)
list1.stream().map(String::toUpperCase).forEach(item -> System.out.println(item));
}
}
在Function中有两个默认实现方法的作用区分:compose()andThen()
下面展示一些 内联代码片
。
/**
* @author curry
* @Date 2022/1/19 11:23
* @since 1.0.0
*/
public class FunctionTest1 {
public static void main(String[] args) {
FunctionTest1 t = new FunctionTest1();
System.out.println(t.compute(2,v -> v*3,v->v*v)); //12
System.out.println(t.compute2(2,v -> v*3,v->v*v)); // 36
}
public int compute(int a, Function<Integer,Integer> function1, Function<Integer,Integer> function2) {
return function1.compose(function2).apply(a);//先参数函数再执行调用的
}
public int compute2(int a, Function<Integer,Integer> function1, Function<Integer,Integer> function2) {
return function1.andThen(function2).apply(a);//先执行调用函数再执行参数函数
}
}
BiFunction<T, U, R>作用类似
下面展示一些 内联代码片
。
/**
* @author curry
* @Date 2022/1/19 13:21
* @since 1.0.0
*/
public class Person {
private int age;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* @author curry
* @Date 2022/1/19 13:20
* @since 1.0.0
*/
public class FunctionTest2 {
public static void main(String[] args) {
Person p1 =new Person(20, "zhangsan");
Person p2 =new Person(30, "lisi");
Person p3 =new Person(40, "wangwu");
List<Person> persons = Arrays.asList(p1,p2,p3);
FunctionTest2 t = new FunctionTest2();
List<Person> peopleResult = t.getPersonsByUsername("lisi",persons);
peopleResult.forEach(person -> System.out.println(person.getName()));
System.out.println("单参数接口函数");
List<Person> peopleResult1 = t.getPersonsByage(22,persons);
peopleResult1.forEach(person -> System.out.println(person.getName()));
System.out.println("双参数接口函数");
//filter有个Predicate函数接口
List<Person> peopleResult2 = t.getPersonsByage1(32,persons,(myAge,myPersons) -> myPersons.stream().filter(person -> person.getAge()>myAge).collect(Collectors.toList()));
peopleResult2.forEach(person -> System.out.println(person.getName()));
System.out.println("双参数接口函数,将行为调用的时候处理");
}
public List<Person> getPersonsByUsername (String username,List<Person> persons) {
return persons.stream().filter(person -> person.getName().equals(username)).collect(Collectors.toList());
}
//没有实现将规则给实际应用的时候调用
public List<Person> getPersonsByage(int age,List<Person> persons) {
BiFunction<Integer,List<Person>,List<Person>> biFunction = (byAge,personResult)->personResult.stream().filter(person -> person.getAge()>24).collect(Collectors.toList());
return biFunction.apply(age,persons);
}
//用函数式接口就可以实现
public List<Person> getPersonsByage1(int age,List<Person> persons,BiFunction<Integer,List<Person>,List<Person>> biFunction) {
return biFunction.apply(age,persons);
}
}
详解请看下篇文章