一、Lambda 表达式核心概念
1. 基本语法
1 2
| (parameters) -> expression (parameters) -> { statements; }
|
2. 类型推断机制
1 2
| Function<String, Integer> lengthFunc = s -> s.length();
|
lambda表达式简化过程:
- 省略输入参数类型
- 参数数量判断:只有一个参数时可以去掉括号
- 代码块简化:只有一行时,可以省略花括号,直接跟在
->
后边
- 使用方法引用
Lambda表达式实际上就是对函数式接口方法的实现
二、方法引用详解
1. 方法引用类型
类型 |
语法格式 |
等效 Lambda 表达式 |
示例 |
静态方法引用 |
ClassName::staticMethod |
args -> ClassName.staticMethod(args) |
Math::max |
实例方法引用(对象) |
object::instanceMethod |
args -> object.instanceMethod(args) |
list::add |
实例方法引用(类) |
ClassName::instanceMethod |
(obj, args) -> obj.instanceMethod(args) |
String::length |
构造方法引用 |
ClassName::new |
args -> new ClassName(args) |
ArrayList::new |
2. 典型应用场景
1 2 3 4 5 6 7 8 9
| List<Integer> numbers = Arrays.asList(1,2,3); numbers.stream().map(String::valueOf);
Supplier<List<String>> listSupplier = ArrayList::new;
Consumer<String> printer = System.out::println;
|
3. 方法引用 vs Lambda
1 2 3 4 5
| Function<String, Integer> f1 = s -> s.length();
Function<String, Integer> f2 = String::length;
|
三、核心函数式接口
函数式接口:只包含一个抽象方法的接口为函数式接口,lambda表达式要求必须为函数式接口
接口中default
方法和static
方法不再计数内。
@FunctionalInterface
注解不是必需的,添加注解可以让编译器识别当前接口为函数时接口,如果接口中定义超过一个abstract
方法时会抛出错误:
Multiple non-overriding abstract methods found in interface cn.probiecoder.lambda.DoubleRandomSupplier
1. 四大基础接口
接口 |
方法签名 |
典型应用 |
Supplier<T> |
T get() |
对象工厂/延迟初始化 |
Consumer<T> |
void accept(T t) |
集合遍历处理 |
Predicate<T> |
boolean test(T t) |
数据过滤 |
Function<T,R> |
R apply(T t) |
数据转换 |
2. 16 种原始类型
输入/输出类型表
输入类型 \ 输出类型 |
T |
int |
long |
double |
T |
UnaryOperator<T> |
ToIntFunction<T> |
ToLongFunction<T> |
ToDoubleFunction<T> |
int |
IntFunction<R> |
IntUnaryOperator |
IntToLongFunction |
IntToDoubleFunction |
long |
LongFunction<R> |
LongToIntFunction |
LongUnaryOperator |
LongToDoubleFunction |
double |
DoubleFunction<R> |
DoubleToIntFunction |
DoubleToLongFunction |
DoubleUnaryOperator |
典型接口详解
接口 |
方法签名 |
应用场景 |
示例代码 |
IntFunction<R> |
R apply(int value) |
int → 任意类型转换 |
IntFunction<String> f = i -> "No." + i; |
ToIntFunction<T> |
int applyAsInt(T t) |
对象 → int 提取 |
ToIntFunction<String> f = String::length; |
IntUnaryOperator |
int applyAsInt(int) |
int → int 运算 |
IntUnaryOperator add5 = x -> x + 5; |
DoubleToIntFunction |
int applyAsInt(double) |
double → int 强制转换 |
DoubleToIntFunction f = d -> (int)d; |
3. 二元操作接口
接口 |
方法签名 |
应用场景 |
BiFunction<T,U,R> |
R apply(T t, U u) |
合并两个对象 |
BiConsumer<T,U> |
void accept(T t, U u) |
消费两个对象 |
BiPredicate<T,U> |
boolean test(T t, U u) |
双参数条件判断 |
1 2 3 4
| BiFunction<List<String>, List<String>, List<String>> merger = (list1, list2) -> Stream.concat(list1.stream(), list2.stream()) .collect(Collectors.toList());
|
四、Lambda 高级特性
1. 变量捕获规则
1 2
| int base = 10; Function<Integer, Integer> adder = x -> x + base;
|
2. 闭包与内存管理
1 2 3 4
| Supplier<IntSupplier> createCounter() { int[] count = {0}; return () -> () -> count[0]++; }
|
五、应用案例
1. 集合处理
1 2 3 4 5 6 7
| List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream() .filter(s -> s.length() > 3) .map(String::toUpperCase) .forEach(System.out::println);
|
2. 工厂模式
1 2 3 4 5
| Map<String, Supplier<Shape>> shapeFactory = new HashMap<>(); shapeFactory.put("circle", Circle::new); shapeFactory.put("square", Square::new);
Shape shape = shapeFactory.get("circle").get();
|
六、性能优化
避免自动装箱:优先使用原始类型特化接口
1 2 3 4 5
| Function<Integer, Integer> f = i -> i * 2;
IntUnaryOperator f = i -> i * 2;
|
缓存 Lambda 表达式:对重复使用的表达式进行复用
1
| private static final Predicate<String> LENGTH_3 = s -> s.length() == 3;
|
谨慎使用并行流:仅在数据量大且无状态操作时启用
1
| list.parallelStream().map(...)
|
附录:JDK 函数式接口全表
接口分类 |
核心接口 |
原始类型特化接口(示例) |
二元接口 |
生产型 |
Supplier<T> |
IntSupplier , DoubleSupplier |
- |
消费型 |
Consumer<T> |
IntConsumer , DoubleConsumer |
BiConsumer<T,U> |
判断型 |
Predicate<T> |
IntPredicate , DoublePredicate |
BiPredicate<T,U> |
转换型 |
Function<T,R> |
IntFunction<R> , ToIntFunction<T> |
BiFunction<T,U,R> |