函数式接口
定义:有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
说明:
- 使用lambda表达式的前提
- 该接口代表了该方法
- 用@FunctionalInterface修饰
public interface A{
public abstract void aa();
}
Lambda表达式
jdk8才出现,8之前都是匿名内部类
作用:可以创建函数式接口的对象。
public class Test {
@org.junit.Test
public void test()
{
//匿名内部类
//匿名内部类使用的局部变量必须是final
Fangzi fangzi = new Fangzi(){
@Override
public void show() {
System.out.println("杜断房谋");
}
};
fangzi.show();
//使用lambda表达式,其实就是匿名内部类的转化
Fangzi fz = ()->{
System.out.println("你防我断");
};
fz.show();
}
}
@FunctionalInterface//检测该接口是否为一个函数式接口,如不是则报错
interface Fangzi{
public void show();
}
Lambda语法
三部分:
- 中间:箭头操作符(lambda)操作符: ->
- 左侧:lambda表达式的参数列表
- 接口中抽象方法的参数列表
- 右侧:lambda表达式所执行的功能,lambda体
- 接口中抽象方法的实现
实现接口抽象方法不同类型
一: 无参数,无返回值
例:
Runnable r1 = () -> System.out.println("hello lambda");
r1.run();
二:一个参数(可以不加括号),无返回值
例:
Consumer(String) con = (string1) -> System.out.println(string1);
con.accept("输出string");
Consumer(String) con = string2 -> System.out.println(string2);
con.accept("输出string");
三:两个以上参数,有返回值,lambda体有多条语句需要写在{}内
例:
Comparator<Integer> com = (x, y) - > {
System.out.println("比较两个参数");
return Integer.compare(x, y);
};
四:两个以上参数,有返回值,lambda体只有一条语句{} 和return 可以省略不写
例:
Comparator<Integer> com = (Integer x, Integer y) - > {Integer.compare(x, y);
Comparator<Integer> com = (x, y) - > {Integer.compare(x, y);
jvm可以做类型推断。因为函数式接口中指定了Integer类型
知识补充
类型推断
例:
List<String> list = new ArrayList<>();
| |
//这里定义了 这里不用写
//jvm可以根据上下文推断出来。
String[] str = {"a", "b", "c"};
//"a", "b", "c",每个元素都是String类型
//String[] str; str = {"a", "b", "c"}; 这样就推断不出了
java 8 四个核心内置函数式接口
1. Comsumer<T>
消费型接口,一个参数,无返回类型
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
```
}
2. Supplier<T>
供给型接口, 无参数,指定返回类型
@FunctionalInterface
public interface Supplier<T> {
T get();
}
3. Predicate<T>
断言接口,一个参数,返回boolean类型
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
```
}
4. Comsumer<T>
函数接口,两个参数,指定返回类型
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
```
}
都有其各自的子接口。
方法引用 (method reference)
Lambda表达式一种更简洁的表达形式。在Lambda体中,使用其它已经实现的方法对Lambda实现接口方法的一种引用(替换)。已经实现的方法 与 Lambda要实现接口的抽象方法 的参数列表与返回类型必须一致才可以使用方法引用。
语法表达形式
- 对象::方法名
```
public class lambdaTest {
@Test
public void testLambda() {
Compare com = new Compare();
BiFunction<Integer, Integer, Integer> biFunction = com::outBig;
System.out.println(biFunction.apply(3, 6));
}
}
class Compare {
public Integer outBig(Integer i, Integer j){
if (i < j) {
return j;
}
return i;
}
}
- 类名::静态方法名
```
public class lambdaTest {
@Test
public void testLambda() {
BiFunction<Integer, Integer, Integer> biFunction = Integer::compare;
System.out.println(biFunction.apply(3, 6));
biFunction = Compare::outBig;
System.out.println(biFunction.apply(3, 6));
}
}
class Compare {
public static Integer outBig(Integer i, Integer j){
if (i < j) {
return j;
}
return i;
}
}
- 类名::实例方法名
使用前提:第一个参数为实例方法的调用者,第二个参数为实例方法的参数
```
public class lambdaTest {
@Test
public void testLambda() {
BiPredicate<String, String> biPredicate = (x, y) -> x.equals(y);//lambda表达式
System.out.println(biPredicate.test("a", "b"));//false
biPredicate = String::equals;//方法引用
System.out.println(biPredicate.test("a", "a"));//true
}
}
构造器引用
对于使用不同构造器取决于要实现接口的方法的参数
语法表达形式
ClassName::new
Supplier<Student> sup = () -> new Student(); //lambda
sup.get();
Supplier<Student> sup1 = Student::new;//构造器引用
//此时使用无参构造
sup1.get();//get无参
Function<String, Student> fun = (str) -> new Student(str);//lambda
Function<String, Student> fun1 = Student::new;
//使用一个参数的有参数构造器
fun1.apply("zhangsan");//apply有参构造,一个参数
数组引用
Function<Integer, String[]> fun = (x) -> new String[x];
System.out.println(fun.apply(10).length);//10
fun = String[]::new;
System.out.println(fun.apply(20).length);//20
Supplier<List> sup = ArrayList::new;
//List