Java 8 四大函数式接口详解

一、核心函数式接口概览

Java 8 引入了四个核心函数式接口,位于 java.util.function 包中:

classDiagram
    class Function{
        +R apply(T t)
    }
    class Consumer{
        +void accept(T t)
    }
    class Supplier{
        +T get()
    }
    class Predicate{
        +boolean test(T t)
    }
图片[1]_Java 8 四大函数式接口详解_知途无界

二、Function 接口详解

2.1 基本定义

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
    
    // 默认方法
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before)
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after)
    static <T> Function<T, T> identity()
}

2.2 使用示例

// 示例1:字符串转整数
Function<String, Integer> strToInt = Integer::parseInt;
int num = strToInt.apply("123"); // 123

// 示例2:组合函数
Function<Integer, Integer> square = x -> x * x;
Function<Integer, String> squareToString = square.andThen(String::valueOf);
String result = squareToString.apply(5); // "25"

// 示例3:方法引用
Function<String, String> toUpperCase = String::toUpperCase;
String upper = toUpperCase.apply("hello"); // "HELLO"

2.3 变种接口

接口方法签名特殊说明
IntFunctionR apply(int value)接收int参数
DoubleFunctionR apply(double value)接收double参数
ToIntFunctionint applyAsInt(T value)返回int结果
BiFunction<T,U,R>R apply(T t, U u)接收两个参数

三、Consumer 接口详解

3.1 基本定义

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
    
    // 默认方法
    default Consumer<T> andThen(Consumer<? super T> after)
}

3.2 使用示例

// 示例1:打印元素
Consumer<String> printer = System.out::println;
printer.accept("Hello World"); // 输出 Hello World

// 示例2:集合遍历
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(printer);

// 示例3:组合消费者
Consumer<String> logger = s -> System.out.println("Log: " + s);
Consumer<String> combined = printer.andThen(logger);
combined.accept("Test"); // 先打印,再记录日志

3.3 变种接口

接口方法签名特殊说明
IntConsumervoid accept(int value)接收int参数
DoubleConsumervoid accept(double value)接收double参数
BiConsumer<T,U>void accept(T t, U u)接收两个参数
ObjIntConsumervoid accept(T t, int value)对象+int参数

四、Supplier 接口详解

4.1 基本定义

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

4.2 使用示例

// 示例1:随机数生成
Supplier<Double> randomSupplier = Math::random;
double random = randomSupplier.get();

// 示例2:对象工厂
Supplier<LocalDate> todaySupplier = LocalDate::now;
LocalDate today = todaySupplier.get();

// 示例3:延迟计算
Supplier<String> expensiveOperation = () -> {
    // 模拟耗时操作
    try { Thread.sleep(1000); } 
    catch (InterruptedException e) {}
    return "Result";
};

4.3 变种接口

接口方法签名特殊说明
BooleanSupplierboolean getAsBoolean()返回boolean
IntSupplierint getAsInt()返回int
LongSupplierlong getAsLong()返回long
DoubleSupplierdouble getAsDouble()返回double

五、Predicate 接口详解

5.1 基本定义

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
    
    // 默认方法
    default Predicate<T> and(Predicate<? super T> other)
    default Predicate<T> or(Predicate<? super T> other)
    default Predicate<T> negate()
    static <T> Predicate<T> isEqual(Object targetRef)
}

5.2 使用示例

// 示例1:字符串过滤
Predicate<String> isEmpty = String::isEmpty;
boolean test = isEmpty.test(""); // true

// 示例2:组合谓词
Predicate<Integer> isEven = n -> n % 2 == 0;
Predicate<Integer> isPositive = n -> n > 0;
Predicate<Integer> isEvenAndPositive = isEven.and(isPositive);
boolean result = isEvenAndPositive.test(4); // true

// 示例3:集合过滤
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream()
                                .filter(isEven)
                                .collect(Collectors.toList()); // [2, 4]

5.3 变种接口

接口方法签名特殊说明
IntPredicateboolean test(int value)接收int参数
LongPredicateboolean test(long value)接收long参数
DoublePredicateboolean test(double value)接收double参数
BiPredicate<T,U>boolean test(T t, U u)接收两个参数

六、高级应用场景

6.1 函数组合

// 函数链式操作
Function<Integer, Integer> add = x -> x + 1;
Function<Integer, Integer> multiply = x -> x * 2;

Function<Integer, Integer> combined = add.andThen(multiply);
int result = combined.apply(3); // (3 + 1) * 2 = 8

// 谓词组合
Predicate<String> startsWithA = s -> s.startsWith("A");
Predicate<String> endsWithE = s -> s.endsWith("e");
Predicate<String> startsWithAOrEndsWithE = startsWithA.or(endsWithE);

6.2 方法引用与Lambda

// 静态方法引用
Function<String, Integer> parseInt = Integer::parseInt;

// 实例方法引用
Consumer<String> print = System.out::println;

// 构造方法引用
Supplier<List<String>> listSupplier = ArrayList::new;

// 对象方法引用
Predicate<String> isEmpty = String::isEmpty;

6.3 Stream API 集成

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

// 使用Predicate过滤
List<String> longNames = names.stream()
    .filter(s -> s.length() > 4)
    .collect(Collectors.toList());

// 使用Function转换
List<Integer> nameLengths = names.stream()
    .map(String::length)
    .collect(Collectors.toList());

// 使用Consumer遍历
names.stream().forEach(System.out::println);

七、性能考量

7.1 内存占用比较

实现方式内存占用说明
匿名类较高每次调用创建新对象
Lambda较低可能共享实例
方法引用最低通常单例实现

7.2 最佳实践

  1. 优先使用方法引用​:更简洁且通常更高效
  2. 避免复杂Lambda​:超过3行的Lambda考虑提取方法
  3. 重用函数实例​:对于常用操作缓存函数对象
  4. 注意闭包捕获​:避免在Lambda中捕获大对象

八、常见问题解答

8.1 接口选择指南

flowchart TD
    A[需要返回值?] -->|是| B{参数数量?}
    A -->|否| C[Consumer]
    B -->|单参数| D[Function]
    B -->|无参数| E[Supplier]
    B -->|双参数| F[BiFunction]
    C --> G{需要条件判断?}
    G -->|是| H[Predicate]
    G -->|否| I[纯Consumer]

8.2 典型错误案例

// 错误1:修改外部变量
int counter = 0;
names.forEach(s -> counter++); // 编译错误

// 错误2:忽略返回值
Function<String, Integer> parser = Integer::parseInt;
parser.apply("123"); // 返回值被忽略

// 错误3:过度嵌套
Function<Integer, Function<Integer, Integer>> adder = x -> y -> x + y; // 可读性差

8.3 调试技巧

  1. 打印中间结果​: Function<String, Integer> debugParser = s -> { System.out.println("Parsing: " + s); return Integer.parseInt(s); };
  2. 使用peek方法​: names.stream() .peek(System.out::println) .filter(s -> s.length() > 3) .forEach(...);
  3. 拆解复杂链式调用​:分步调试各函数结果

九、扩展应用示例

9.1 自定义函数式接口

@FunctionalInterface
interface TriFunction<T, U, V, R> {
    R apply(T t, U u, V v);
}

// 使用示例
TriFunction<Integer, Integer, Integer, Integer> sumThree = 
    (a, b, c) -> a + b + c;
int total = sumThree.apply(1, 2, 3); // 6

9.2 高阶函数

// 接收函数作为参数
public static <T, R> List<R> transformList(
    List<T> list, Function<T, R> transformer) {
    return list.stream()
              .map(transformer)
              .collect(Collectors.toList());
}

// 返回函数
public static Function<String, String> createPrefixer(String prefix) {
    return s -> prefix + s;
}

9.3 函数式设计模式

// 策略模式
public class Validator {
    private final Predicate<String> strategy;
    
    public Validator(Predicate<String> strategy) {
        this.strategy = strategy;
    }
    
    public boolean validate(String input) {
        return strategy.test(input);
    }
}

// 使用
Validator numberValidator = new Validator(s -> s.matches("\\d+"));
boolean isValid = numberValidator.validate("123"); // true

关键要点总结​:

  1. Function 用于转换操作,接收T返回R
  2. Consumer 用于消费操作,无返回值
  3. Supplier 用于提供数据,无参数有返回值
  4. Predicate 用于条件判断,返回boolean
  5. Java 8提供了40+个函数式接口变种满足特殊需求
  6. 合理使用函数组合可以大幅提升代码表达能力
  7. 在Stream API中函数式接口发挥核心作用
© 版权声明
THE END
喜欢就点个赞,支持一下吧!
点赞73 分享
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容