引言:什么是函数式接口?
函数式接口(Functional Interface)是Java 8引入的概念,指的是只包含一个抽象方法的接口。可以用@FunctionalInterface注解标记,也支持Lambda表达式和方法引用。
函数式接口类比
想象一个插座:
普通接口 = 复杂多功能插座(很多方法)
函数式接口 = 单一功能插座(只有一个功能)
函数式接口就像:
USB接口 → 只做一件事:充电/数据传输
而不是:
万能插座 → 什么都想做,什么都做不好
@FunctionalInterface注解
使用@FunctionalInterface注解可以让编译器帮助检查接口是否符合函数式接口的定义。
@FunctionalInterface
public interface MyFunction {
int apply(int a, int b);
}
// 正确:只有一个抽象方法
@FunctionalInterface
interface Calculator {
int calculate(int a, int b);
}
// 错误:多个抽象方法,编译报错
@FunctionalInterface
interface WrongInterface {
void method1();
void method2(); // 编译错误!
}
// 函数式接口也可以有默认方法(不计入抽象方法)
@FunctionalInterface
interface WithDefault {
void execute();
default void log() { // 默认方法不计入抽象方法
System.out.println("执行");
}
}
四大核心函数式接口
| 接口 | 抽象方法 | 参数 | 返回值 | 用途 |
|---|---|---|---|---|
| Predicate<T> | test(T) | 1个 | boolean | 判断/过滤 |
| Function<T,R> | apply(T) | 1个 | R | 转换/映射 |
| Consumer<T> | accept(T) | 1个 | void | 消费/处理 |
| Supplier<T> | get() | 0个 | T | 生产/提供 |
Predicate - 判断接口
Predicate<T>接收一个参数,返回boolean值,用于判断条件。
接口定义
@FunctionalInterface
public interface Predicate {
boolean test(T t);
// 默认方法
default Predicate and(Predicate super T> other);
default Predicate or(Predicate super T> other);
default Predicate negate();
static Predicate isEqual(Object targetRef);
}
基本使用
Predicate isEmpty = s -> s.isEmpty();
Predicate isNotEmpty = isEmpty.negate();
System.out.println(isEmpty.test("")); // true
System.out.println(isNotEmpty.test("hello")); // true
Predicate isPositive = n -> n > 0;
System.out.println(isPositive.test(10)); // true
System.out.println(isPositive.test(-5)); // false
组合条件:and / or
Predicate isPositive = n -> n > 0;
Predicate isEven = n -> n % 2 == 0;
// and:同时满足
Predicate isPositiveEven = isPositive.and(isEven);
System.out.println(isPositiveEven.test(4)); // true (正数且偶数)
System.out.println(isPositiveEven.test(3)); // false (正数但奇数)
// or:满足其一
Predicate isPositiveOrEven = isPositive.or(isEven);
System.out.println(isPositiveOrEven.test(4)); // true (正数且偶数)
System.out.println(isPositiveOrEven.test(-2)); // true (负数但偶数)
System.out.println(isPositiveOrEven.test(-3)); // false (负数且奇数)
// negate:取反
Predicate isNotPositive = isPositive.negate();
System.out.println(isNotPositive.test(-5)); // true
isEqual静态方法
Predicate isJava = Predicate.isEqual("Java");
System.out.println(isJava.test("Java")); // true
System.out.println(isJava.test("Python")); // false
// 在Stream中使用
List languages = Arrays.asList("Java", "Python", "Java", "C++");
long javaCount = languages.stream()
.filter(Predicate.isEqual("Java"))
.count();
System.out.println("Java出现次数: " + javaCount); // 2
Predicate在Stream中的应用
List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 过滤正数
List positives = numbers.stream()
.filter(n -> n > 0)
.collect(Collectors.toList());
// 过滤偶数
List evens = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
// 组合条件:大于5的奇数
List result = numbers.stream()
.filter(n -> n > 5 && n % 2 != 0)
.collect(Collectors.toList());
Function - 转换接口
Function<T,R>接收一个参数,返回一个结果,用于类型转换/映射。
接口定义
@FunctionalInterface
public interface Function {
R apply(T t);
// 默认方法
default Function compose(Function super V, ? extends T> before);
default Function andThen(Function super R, ? extends V> after);
static Function identity();
}
基本使用
Function length = s -> s.length();
System.out.println(length.apply("hello")); // 5
Function upper = s -> s.toUpperCase();
System.out.println(upper.apply("hello")); // HELLO
Function toStr = i -> String.valueOf(i);
System.out.println(toStr.apply(100)); // "100"
链式调用:andThen / compose
Function trim = s -> s.trim();
Function upper = s -> s.toUpperCase();
Function toStr = s -> "Result: " + s;
// andThen:先执行当前,再执行after
Function pipeline1 = trim.andThen(upper).andThen(toStr);
System.out.println(pipeline1.apply(" hello ")); // "Result: HELLO"
// compose:先执行before,再执行当前(顺序相反)
Function pipeline2 = toStr.compose(upper).compose(trim);
System.out.println(pipeline2.apply(" hello ")); // "Result: HELLO"
// identity:返回输入本身
Function identity = Function.identity();
System.out.println(identity.apply("test")); // "test"
多步转换示例
List names = Arrays.asList(" alice ", " BOB ", " Charlie ");
// 链式转换:去空格 -> 转大写 -> 加前缀
List result = names.stream()
.map(s -> s.trim()) // 去空格
.map(s -> s.toUpperCase()) // 转大写
.map(s -> "Name: " + s) // 加前缀
.collect(Collectors.toList());
System.out.println(result);
// [Name: ALICE, Name: BOB, Name: CHARLIE]
Consumer - 消费接口
Consumer<T>接收一个参数,不返回结果,用于消费/处理数据。
接口定义
@FunctionalInterface
public interface Consumer {
void accept(T t);
// 默认方法
default Consumer andThen(Consumer super T> after);
}
基本使用
Consumer printer = s -> System.out.println(s);
printer.accept("Hello World"); // 打印 Hello World
Consumer exclaimer = s -> System.out.println(s + "!");
printer.accept("Hi"); // 打印 Hi
exclaimer.accept("Hi"); // 打印 Hi!
andThen组合
Consumer trim = s -> System.out.println(s.trim());
Consumer upper = s -> System.out.println(s.toUpperCase());
// 先执行trim,再执行upper
Consumer consumer = trim.andThen(upper);
consumer.accept(" hello ");
// 输出:
// hello
// HELLO
在Stream中使用
List names = Arrays.asList("Alice", "Bob", "Charlie");
// forEach接收Consumer
names.forEach(name -> System.out.println("Hello, " + name));
names.forEach(System.out::println);
// 打印每个元素的详细信息
names.forEach(name -> {
System.out.println("==========");
System.out.println("Name: " + name);
System.out.println("Length: " + name.length());
});
Supplier - 生产接口
Supplier<T>不接收参数,返回一个结果,用于生产/提供数据。
接口定义
@FunctionalInterface
public interface Supplier {
T get();
}
基本使用
Supplier helloSupplier = () -> "Hello";
System.out.println(helloSupplier.get()); // "Hello"
// 创建对象
Supplier> listSupplier = () -> new ArrayList<>();
ArrayList list = listSupplier.get();
list.add("item");
// 创建Random对象
Supplier randomSupplier = Random::new;
Random random = randomSupplier.get();
System.out.println(random.nextInt(100)); // 0-99的随机数
实际应用场景
// 延迟计算/初始化
Supplier configSupplier = () -> loadConfiguration();
Configuration config = configSupplier.get(); // 实际使用时才加载
// 使用Optional
Optional optional = Optional.of("value");
// orElseGet是Supplier,当值为空时才调用
String value = optional.orElseGet(() -> "default");
// 方法引用创建对象
Supplier> listFactory = ArrayList::new;
Supplier> mapFactory = HashMap::new;
其他常用函数式接口
| 接口 | 方法 | 说明 |
|---|---|---|
| BiPredicate<T,U> | test(T,U) | 两个参数的判断 |
| BiFunction<T,U,R> | apply(T,U) | 两个参数的转换 |
| BiConsumer<T,U> | accept(T,U) | 两个参数的消费 |
| UnaryOperator<T> | apply(T) | 一元操作,结果同类型 |
| BinaryOperator<T> | apply(T,T) | 二元操作,结果同类型 |
| IntPredicate | test(int) | 原始类型int的判断 |
| IntFunction<R> | apply(int) | 接收int,返回R |
| ToIntFunction<T> | applyAsInt(T) | 返回int的转换 |
BiFunction示例
// 两个参数,返回一个结果
BiFunction concat = (s1, s2) -> s1 + s2;
System.out.println(concat.apply("Hello", "World")); // "HelloWorld"
BiFunction add = (a, b) -> a + b;
System.out.println(add.apply(10, 20)); // 30
// 链式调用
BiFunction pipeline = concat.andThen(s -> s.toUpperCase());
System.out.println(pipeline.apply("hello", "world")); // "HELLOWORLD"
UnaryOperator和BinaryOperator
// UnaryOperator:一元操作,输入输出类型相同
UnaryOperator square = n -> n * n;
System.out.println(square.apply(5)); // 25
UnaryOperator upper = String::toUpperCase;
System.out.println(upper.apply("hello")); // HELLO
// BinaryOperator:二元操作,输入两个同类型值,返回同类型结果
BinaryOperator add = (a, b) -> a + b;
System.out.println(add.apply(10, 20)); // 30
BinaryOperator max = (s1, s2) -> s1.length() > s2.length() ? s1 : s2;
System.out.println(max.apply("apple", "banana")); // "banana"
// 求最大值/最小值
BinaryOperator maxInt = BinaryOperator.maxBy(Integer::compare);
BinaryOperator minInt = BinaryOperator.minBy(Integer::compare);
原始类型函数式接口
// 避免自动装箱/拆箱,提高性能
IntFunction intToString = i -> String.valueOf(i);
System.out.println(intToString.apply(100)); // "100"
ToIntFunction strToLength = String::length;
System.out.println(strToLength.applyAsInt("hello")); // 5
IntBinaryOperator sum = (a, b) -> a + b;
System.out.println(sum.applyAsInt(10, 20)); // 30
IntUnaryOperator doubleValue = n -> n * 2;
System.out.println(doubleValue.applyAsInt(5)); // 10
函数式接口的选择
需要判断? → Predicate
需要转换? → Function
需要处理但不返回? → Consumer
需要创建对象? → Supplier
两个参数? → Bi* 系列
避免装箱拆箱? → Int*/Long*/Double*
实战示例
构建查询条件
public class QueryBuilder {
private List> conditions = new ArrayList<>();
public QueryBuilder whenNameContains(String name) {
conditions.add(s -> s.contains(name));
return this;
}
public QueryBuilder whenNameStartsWith(String prefix) {
conditions.add(s -> s.startsWith(prefix));
return this;
}
public QueryBuilder whenNameNotEmpty() {
conditions.add(s -> !s.isEmpty());
return this;
}
public Predicate build() {
Predicate result = s -> true;
for (Predicate p : conditions) {
result = result.and(p);
}
return result;
}
}
// 使用
QueryBuilder builder = new QueryBuilder();
Predicate query = builder
.whenNameNotEmpty()
.whenNameStartsWith("A")
.build();
System.out.println(query.test("Alice")); // true
System.out.println(query.test("Bob")); // false
数据转换流水线
public class DataPipeline {
public static List process(
List data,
Function mapper,
Consumer consumer) {
List result = data.stream()
.map(mapper)
.collect(Collectors.toList());
result.forEach(consumer);
return result;
}
}
// 使用
List names = Arrays.asList(" alice ", " bob ", " charlie ");
List processed = DataPipeline.process(
names,
s -> s.trim().toUpperCase(), // Function
s -> System.out.println("Processed: " + s) // Consumer
);
System.out.println("Result: " + processed);
小结
- 函数式接口是只有一个抽象方法的接口
- @FunctionalInterface注解用于编译器检查
- Predicate<T>:判断,返回boolean → filter()
- Function<T,R>:转换,T→R → map()
- Consumer<T>:消费,无返回值 → forEach()
- Supplier<T>:生产,无参数 → orElseGet()
- Bi* 系列:处理两个参数
- 原始类型接口(Int*):避免装箱拆箱,提高性能