1、什么是函数式(Functional)接口?
(1)只包含一个抽象方法的接口,称为函数式接口
(2)你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda 表达式抛出一个受检异常(即:非运行时异常),那么该异常需要在目标接口的抽象方法上进行声明)
(3)我们可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口。同时 java doc 也会包含一条声明,说明这个接口是一个函数式接口
(4)在java.util.function包下定义了java 8 的丰富的函数式接口
判断是否是函数式接口
@FunctionalInterface
interface I1 {
void play(String str);
}
//判断是否是函数式接口
@FunctionalInterface
interface I4 {
void start();
void stop();
}
2、如何理解函数式接口?
(1)Java从诞生日起就是一直倡导“一切皆对象”,在java里面面向对象(OOP)编程是一切。但是随着python、scala等语言的兴起和新技术的挑战,java不得不做出调整以便支持更加广泛的技术要求,也即java不但可以支持OOP还可以支持OOF(面向函数编程)
(2)在函数式编程语言当中,函数被当做一等公民对待。在将函数作为一等公民的编程语言中,Lambda表达式的类型是函数。但是在Java8中,有所不同。在Java8中,Lambda表达式是对象,而不是函数,它们必须依附于一类特别的对象类型——函数式接口
(3)简单的说,在Java8中,Lambda表达式就是一个函数式接口的实例。这就是Lambda表达式和函数式接口的关系。也就是说,只要一个对象是函数式接口的实例,那么该对象就可以用Lambda表达式来表示。 所以以前用匿名内部类表示的现在都可以用Lambda表达式来写
3、函数式接口举例
4、自定义函数式接口
@FunctionalInterface
interface MyNumber {
public double getValue();
}
//函数式接口中使用泛型
@FunctionalInterface
interface MyFun<T> {
public T getValue(T t);
}
5、作为参数传递 Lambda 表达式
作为参数传递 Lambda 表达式:为了将 Lambda 表达式作为参数传递,接收Lambda 表达式的参数类型必须是与该 Lambda 表达式兼容的函数式接口的类型。
6、Java 内置函数式接口
(1)Java 内置四大核心函数式接口(常用且重要
)
(2)其他接口(不用掌握,感兴趣可以自己做测试
)
7、函数式接口案例
(1)Consumer<T> :消费性接口
package com.yinggu.demo3;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.junit.Test;
import com.yinggu.data.EmployeeData;
import com.yinggu.domain.Employee;
* @author 黑猴子的家
* http://www.121ugrow.com/
* 此类用于演示函数式接口的使用 函数式接口:
* 里面只有一个抽象方法的接口称为函数式接口
* 只有函数式接口,才可以使用Lambda表达式生成对象
* Consumer<T> :消费性接口 有参数 无返回
* Supplier<T> :供给型接口 无参数 有返回
* Function<T,R>:函数型接口 有参数 有返回
* Predicate<T> :断定型接口 有参数 有返回(true 或 false)
public class TestFunctionalInterface {
/**
* Consumer<T> :消费性接口 有参数 无返回
*/
@Test
public void testConsumer() {
Consumer<Double> con = money -> {
if (money > 1000)
System.out.println("去k歌");
else if (money > 500)
System.out.println("去泡澡");
else
System.out.println("麻辣烫");
};
con.accept(580.0);
}
}
(2)Supplier<T> :供给型接口 无参数有返回
/**
* Supplier<T> :供给型接口 无参数 有返回
*/
@Test
public void testSupplier() {
Supplier<String> sup = () -> "苍老师".substring(0, 1);
System.out.println(sup.get());
}
(3)Function<T,R>:函数型接口-有参数有返回
方式一
/**
* Function<T,R>:函数型接口 有参数 有返回
*/
@Test
public void testFunction1() {
Function<String, Integer> fun = str -> str.length();
System.out.println(fun.apply("迪丽热巴"));
}
方式二
/**
* Function<T,R>:函数型接口 有参数 有返回
*/
@Test
public void testFunction2() {
// 根据编号返回员工对象
/*
* 参数:int id——》Integer 返回:employee对象——》Employee
*/
Function<Integer, Employee> fun = id -> {
// 查找员工对象的步骤
List<Employee> list = EmployeeData.getData();
for (Employee employee : list) {
if (id == employee.getId()) {
return employee;
}
}
return null;
};
System.out.println(fun.apply(5));
}
(4)Predicate<T> :断定型接口-有参数有返回(true或false)
方式一
/**
* Predicate<T> :断定型接口 有参数 有返回(true 或 false)
* 判断字符串的长度是不是3
*/
@Test
public void testPredicate() {
Predicate<String> pre = str -> str.length() == 3;
System.out.println(pre.test("段誉"));
}
方式二
/**
* Predicate<T> :断定型接口 有参数 有返回(true 或 false)
* 求满足条件的员工信息
*/
@Test
public void testPredicate2() {
List<Employee> list = EmployeeData.getData();
// 1.需求1:过滤年龄大于30岁
List<Employee> data1 = getData(list, emp -> emp.getAge() > 30);
for (Employee employee : data1) {
System.out.println(employee);
}
System.out.println("-------------");
// 2.需求2:过滤工资>20000
List<Employee> data2 = getData(list, emp -> emp.getSalary() > 20000);
for (Employee employee : data2) {
System.out.println(employee);
}
}
//定义一个方法
public List<Employee> getData(List<Employee> list, Predicate<Employee> pre) {
List<Employee> data = new ArrayList<>();
for (Employee employee : list) {
if (pre.test(employee)) {
data.add(employee);
}
}
return data;
}