Java 8引入的函数式接口(Functional Interface)是支持Lambda表达式的核心概念,它通过单一抽象方法(SAM)的接口简化代码编写。以下是其分类和使用的详细说明:
一、函数式接口的核心特征- 定义:标注@FunctionalInterface的接口,且仅有一个待实现的抽象方法(默认方法或静态方法不计入)。
- 作用:允许用Lambda表达式或方法引用替代匿名内部类,提升代码简洁性。
- 常见位置:java.util.function包中集中定义了多种函数式接口。
二、主要分类及使用场景1. Function(函数型)- 特点:接收一个参数,返回一个结果。
- 核心接口:@FunctionalInterfacepublic interface Function<T, R> { R apply(T t);}
- 变体:
指定参数类型:IntFunction<R>、LongFunction<R>、DoubleFunction<R>。
指定返回类型:ToIntFunction<T>、ToLongFunction<T>、ToDoubleFunction<T>。
双向指定:DoubleToIntFunction、IntToLongFunction等。
- 示例:Map<String, Integer> map = new HashMap<>();map.computeIfAbsent("key", s -> s.length()); // Lambdamap.computeIfAbsent("key", String::length); // 方法引用
2. BiFunction(双参数函数型)- 特点:接收两个参数,返回一个结果。
- 核心接口:@FunctionalInterfacepublic interface BiFunction<T, U, R> { R apply(T t, U u);}
- 变体:ToDoubleBiFunction<T, U>、ToIntBiFunction<T, U>等。
- 示例:Map<String, Integer> salaries = new HashMap<>();salaries.replaceAll((name, oldValue) -> name.equals("alice") ? oldValue : oldValue + 100);
3. Supplier(供给型)- 特点:无参数,返回一个结果。
- 核心接口:@FunctionalInterfacepublic interface Supplier<T> { T get();}
- 示例:Supplier<Double> randomValue = () -> Math.random();
4. Consumer(消费型)- 特点:接收一个参数,无返回值。
- 核心接口:@FunctionalInterfacepublic interface Consumer<T> { void accept(T t);}
- 变体:BiConsumer<T, U>(双参数)。
- 示例:List<String> names = Arrays.asList("Alice", "Bob");names.forEach(name -> System.out.println("Hello, " + name));
5. Predicate(断言型)- 特点:接收一个参数,返回boolean。
- 核心接口:@FunctionalInterfacepublic interface Predicate<T> { boolean test(T t);}
- 变体:BiPredicate<T, U>(双参数)。
- 示例:List<String> filtered = names.stream() .filter(name -> name.startsWith("A")) .collect(Collectors.toList());
6. Operator(运算型)- 特点:参数与返回类型相同,用于运算。
- 子类:
一元运算:UnaryOperator<T>(继承自Function<T, T>)。
二元运算:BinaryOperator<T>(继承自BiFunction<T, T, T>)。
基础类型变体:IntUnaryOperator、LongBinaryOperator等。
- 示例:List<Integer> numbers = Arrays.asList(1, 2, 3);int sum = numbers.stream().reduce(0, (a, b) -> a + b);
三、使用注意事项- Lambda适配规则:
Lambda表达式的参数和返回值必须与函数式接口的抽象方法匹配。
例如:Function<String, Integer>的Lambda需为String -> Integer。
- 方法引用:
静态方法:ClassName::staticMethod
实例方法:instance::method
构造方法:ClassName::new
- 默认方法:
函数式接口可包含default方法(如Function.andThen()),但不影响SAM特性。
四、实际应用场景- 线程池任务:Runnable(无参无返回值)。executor.submit(() -> System.out.println("Task running"));
- 集合操作:Stream API中广泛使用(如map()用Function,filter()用Predicate)。
- 回调机制:Supplier用于延迟计算,Consumer用于事件处理。
五、总结函数式接口通过标准化抽象方法,使Lambda表达式能够无缝集成到Java中。掌握其分类(如Function、Predicate、Operator等)和典型用法,可以显著提升代码的简洁性和可读性。建议结合Stream API和集合操作多加练习,以深入理解其应用场景。
参考代码示例:
GitHub链接
更多学习资源:www.flydean.com