一、函数式接口的定义
函数式接口 (Functional Interface) 是Java 8引入的核心概念,它是指有且仅有一个抽象方法的接口 (可包含默认方法和静态方法)。这种接口可以用Lambda表达式 或方法引用来实现,是函数式编程在Java中的基础。
java
// 标准定义
@FunctionalInterface // 编译期检查,可选但推荐
public interface MyFunction {
String apply(int x); // 唯一的抽象方法
// 允许默认方法
default void print(String msg) {
System.out.println(msg);
}
// 允许静态方法
static void log(String msg) {
System.out.println("[LOG] " + msg);
}
}
二、渐进式学习------代码示例
2.1 阶段1:从匿名类到Lambda演化
java
public class EvolutionDemo {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// 【传统方式】匿名内部类
names.forEach(new Consumer<String>() {
@Override
public void accept(String name) {
System.out.println(name);
}
});
// 【方式1】Lambda完整语法
names.forEach((String name) -> {
System.out.println(name);
});
// 【方式2】Lambda简化(参数类型推导)
names.forEach((name) -> System.out.println(name));
// 【方式3】Lambda最简(单参数可省括号)
names.forEach(name -> System.out.println(name));
// 【方式4】方法引用(终极简化)
names.forEach(System.out::println);
}
}
2.2 阶段2:Java内置的四大核心函数式接口精讲
1. Consumer<T> - 消费型接口
java
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
作用 :接收一个参数,不返回结果
示例:
java
// 打印字符串
Consumer<String> printer = s -> System.out.println(s);
printer.accept("Hello, Consumer!");
// 消费列表元素
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println("Hello, " + name));
2. Supplier<T>- 供给型接口
java
@FunctionalInterface
public interface Supplier<T> {
T get();
}
作用 :不接收参数,返回一个结果
示例:
java
// 生成随机数
Supplier<Double> randomSupplier = () -> Math.random();
System.out.println("Random: " + randomSupplier.get());
// 延迟初始化
Supplier<String> lazyString = () -> {
System.out.println("Initializing...");
return "Lazy Value";
};
System.out.println("Before get");
System.out.println(lazyString.get());
3. Function<T, R> - 函数型接口
java
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
作用 :接收一个参数,返回一个结果
示例:
java
// 字符串转整数
Function<String, Integer> stringToInt = s -> Integer.parseInt(s);
int result = stringToInt.apply("123");
System.out.println("Result: " + result);
// 函数组合
Function<Integer, Integer> doubleIt = x -> x * 2;
Function<Integer, Integer> addOne = x -> x + 1;
Function<Integer, Integer> composed = doubleIt.andThen(addOne);
System.out.println("Composed: " + composed.apply(5)); // 输出: 11
4. Predicate<T> - 断言型接口
java
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
作用 :接收一个参数,返回布尔值
示例:
java
// 判断字符串是否为空
Predicate<String> isEmpty = s -> s == null || s.isEmpty();
System.out.println("Is empty: " + isEmpty.test("")); // true
// 过滤列表
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
System.out.println("Even numbers: " + evenNumbers); // [2, 4, 6]
2.3 阶段3:自定义函数式接口实践
java
// 定义业务相关的函数式接口
@FunctionalInterface
interface OrderValidator {
boolean validate(Order order);
// 默认方法:组合验证
default OrderValidator and(OrderValidator other) {
return order -> this.validate(order) && other.validate(order);
}
}
// 使用自定义接口
public class CustomFunctionalInterface {
public static void main(String[] args) {
List<Order> orders = createOrders();
// 定义验证规则
OrderValidator isActive = Order::isActive;
OrderValidator isHighValue = o -> o.getAmount() > 1000;
// 组合验证(利用默认方法)
OrderValidator combined = isActive.and(isHighValue);
// 应用验证
orders.stream()
.filter(combined::validate) // 方法引用
.forEach(o -> System.out.println("Valid: " + o));
}
}
2.4 阶段4:方法引用与构造函数引用
java
public class ReferenceDemo {
public static void main(String[] args) {
List<String> names = Arrays.asList("Tom", "Jerry");
// 1. 静态方法引用:类名::静态方法
names.stream()
.map(String::toUpperCase) // 等价于 s -> s.toUpperCase()
.forEach(System.out::println);
// 2. 实例方法引用:对象::实例方法
String prefix = "Name: ";
names.forEach(s -> System.out.println(prefix + s));
// 3. 构造函数引用:类名::new
Supplier<List<String>> listSupplier = ArrayList::new;
List<String> newList = listSupplier.get();
// 4. 数组构造函数引用:类型[]::new
IntFunction<String[]> arrayCreator = String[]::new;
String[] array = arrayCreator.apply(5); // 创建长度为5的数组
}
}
2.5 阶段5:Stream API中的函数式接口应用
java
public class StreamFunctionalDemo {
public static void main(String[] args) {
List<Employee> employees = Arrays.asList(
new Employee("Alice", 8000, "Tech"),
new Employee("Bob", 12000, "Tech"),
new Employee("Charlie", 7000, "HR")
);
// 综合案例:分组、过滤、转换
Map<String, List<String>> result = employees.stream()
.filter(e -> e.getSalary() > 7500) // Predicate
.map(Employee::getName) // Function
.collect(Collectors.groupingBy(
name -> name.substring(0, 1) // Function
));
System.out.println(result); // {A=[Alice], B=[Bob]}
}
}
2.6 综合实战案例
java
// 构建一个函数式风格的订单处理系统
public class OrderProcessor {
// 核心:用函数式接口定义可组合的业务规则
private final Function<Order, Double> taxCalculator;
private final Predicate<Order> validationRule;
private final Consumer<Order> auditLogger;
// 构造函数注入行为
public OrderProcessor(Function<Order, Double> taxCalculator,
Predicate<Order> validationRule,
Consumer<Order> auditLogger) {
this.taxCalculator = taxCalculator;
this.validationRule = validationRule;
this.auditLogger = auditLogger;
}
public void process(List<Order> orders) {
orders.stream()
.filter(validationRule) // 验证
.peek(auditLogger) // 记录日志
.map(order -> { // 计算税后价格
double tax = taxCalculator.apply(order);
order.setFinalPrice(order.getAmount() + tax);
return order;
})
.forEach(order -> System.out.println("处理完成: " + order));
}
public static void main(String[] args) {
// 配置不同的业务规则
OrderProcessor domesticProcessor = new OrderProcessor(
order -> order.getAmount() * 0.1, // 10%税
Order::isActive, // 仅处理激活订单
o -> System.out.println("审计: " + o.getId())
);
domesticProcessor.process(createOrders());
}
}
三、总结
在四大核心函数式函数式接口的基础上,还有BiFunction<T, U, R> - 双参数转换、UnaryOperator<T> - 一元操作、BinaryOperator<T> - 二元操作。简单来说,UnaryOperator和BinaryOperator并非新的概念,而是两大核心函数式接口的"特化"或"简化版"。它们与四大核心函数接口的关系是包含与被包含的关系,而非并列关系。
| 接口类型 | 方法签名 | 用途 | 示例 |
|---|---|---|---|
| Consumer | void accept(T t) | 消费数据 | forEach |
| Supplier | T get() | 提供数据 | 延迟初始化 |
| Function<T, R> | R apply(T t) | 数据转换 | map |
| Predicate | boolean test(T t) | 条件判断 | filter |
| BiFunction<T, U, R> | R apply(T t, U u) | 双参数转换 | 合并操作 |
| UnaryOperator | T apply(T t) | 一元操作 | 字符串处理 |
| BinaryOperator | T apply(T t1, T t2) | 二元操作 | 数学运算 |
- Function和 BiFunction 是基础且通用的转换接口,适用于各种复杂的类型转换场景。
- UnaryOperator和 BinaryOperator 是前两者的特殊形式,专门用于输入输出类型一致的特定场景,使代码意图更明确。
如果有需要,也可以使用@FunctionalInterface注解来定制契合某个业务的函数式接口。