Java Lambda表达式详细使用教程
Lambda表达式是Java 8引入的一个重要特性,它允许我们以更简洁的方式表示匿名函数。本教程将详细介绍Java Lambda表达式的语法、用法和应用场景。
1. Lambda表达式基础
1.1 基本语法
Java Lambda表达式的基本语法如下:
(参数列表) -> {
表达式或语句块 }
- 参数列表:可以为空或包含多个参数,类型可以显式声明或由编译器推断
- 箭头操作符:
->
将参数列表与Lambda体分开 - Lambda体:包含表达式或语句块
1.2 简化规则
Lambda表达式可以根据以下规则进行简化:
- 当参数只有一个且类型可推断时,可以省略参数的小括号
- 当Lambda体只有一条语句时,可以省略大括号
- 当Lambda体只有一条返回语句时,可以省略return关键字
// 标准形式
(int x, int y) -> {
return x + y; }
// 省略参数类型
(x, y) -> {
return x + y; }
// 省略大括号和return关键字
(x, y) -> x + y
// 单个参数时省略小括号
x -> x * x
2. 函数式接口
Lambda表达式需要与函数式接口配合使用。函数式接口是只包含一个抽象方法的接口,可以使用@FunctionalInterface
注解标记。
2.1 常用函数式接口
Java 8在java.util.function
包中提供了许多预定义的函数式接口:
import java.util.function.*;
public class FunctionalInterfacesDemo {
public static void main(String[] args) {
// Predicate<T> - 接收T类型参数,返回boolean
Predicate<Integer> isPositive = x -> x > 0;
System.out.println("Is 5 positive? " + isPositive.test(5)); // true
// Function<T, R> - 接收T类型参数,返回R类型结果
Function<Integer, String> intToString = x -> "Number: " + x;
System.out.println(intToString.apply(10)); // Number: 10
// Consumer<T> - 接收T类型参数,无返回值
Consumer<String> printer = s -> System.out.println("Consuming: " + s);
printer.accept("Hello Lambda"); // Consuming: Hello Lambda
// Supplier<T> - 无参数,返回T类型结果
Supplier<Double> randomValue = () -> Math.random();
System.out.println("Random value: " + randomValue.get()); // 随机数
// BiFunction<T, U, R> - 接收T和U类型参数,返回R类型结果
BiFunction<Integer, Integer, Integer> add = (x, y) -> x + y;
System.out.println("5 + 3 = " + add.apply(5, 3)); // 8
// UnaryOperator<T> - Function的特例,输入和输出类型相同
UnaryOperator<Integer> square = x -> x * x;
System.out.println("Square of 4: " + square.apply(4)); // 16
// BinaryOperator<T> - BiFunction的特例,两个输入和输出类型都相同
BinaryOperator<Integer> multiply = (x, y) -> x * y;
System.out.println("4 * 5 = " + multiply.apply(4, 5)); // 20
}
}
2.2 自定义函数式接口
我们也可以创建自己的函数式接口:
@FunctionalInterface
interface MathOperation {
int operate(int a, int b);
// 可以包含默认方法
default MathOperation andThen(MathOperation after) {
return (a, b) -> after.operate(this.operate(a, b), 0);
}
// 可以包含静态方法
static MathOperation addition() {
return (a, b) -> a + b;
}
}
public class CustomFunctionalInterfaceDemo {
public static void main(String[] args) {
// 使用Lambda表达式实现自定义函数式接口
MathOperation addition = (a, b) -> a + b;
MathOperation subtraction = (a, b) -> a - b;
System.out.println("10 + 5 = " + addition.operate(10, 5)); // 15
System.out.println("10 - 5 = " + subtraction.operate(10, 5)); // 5
// 使用默认方法
MathOperation addThenMultiplyBy2 = addition.andThen((a, b) -> a * 2);
System.out.println("(10 + 5) * 2 = " + addThenMultiplyBy2.operate(10, 5)); // 30
// 使用静态方法
MathOperation add = MathOperation.addition();
System.out.println("7 + 3 = " + add.operate(7, 3)); // 10
}
}
3. Lambda表达式与集合操作
Lambda表达式与Stream API结合,可以大大简化集合操作。
3.1 遍历集合
import java.util.Arrays;
import java.util.List;
public class CollectionTraversalDemo {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave");
// 传统方式
System.out.println("传统for循环:");
for (int i = 0; i < names.size(); i++) {
System.out.println(names.get(i));
}
// 增强for循环
System.out.println("\n增强for循环:");
for (String name : names) {
System.out.println(name);
}
// Lambda表达式 - forEach
System.out.println("\nLambda forEach:");
names.forEach(name -> System.out.println(name));
// 方法引用 - 更简洁的Lambda
System.out.println("\n方法引用:");
names.forEach(System.out::println);
}
}
3.2 过滤、映射和归约
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamOperationsDemo {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 过滤 - 获取偶数
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
System.out.println("偶数: " + evenNumbers); // [2, 4, 6, 8, 10]
// 映射 - 将每个数平方
List<Integer> squaredNumbers = numbers.stream()
.map(n -> n * n)
.collect(Collectors.toList());
System.out.println("平方后: " + squaredNumbers); // [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
// 归约 - 求和
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
System.out.println("总和: " + sum); // 55
// 方法引用形式的归约
int product = numbers.stream()
.reduce(1, (a, b) -> a * b);
System.out.println("乘积: " + product); // 3628800
// 组合操作 - 获取偶数的平方和
int sumOfSquaresOfEvens = numbers.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.reduce(0, Integer::sum);
System.out.println("偶数平方和: " + sumOfSquaresOfEvens); // 220
}
}
4. 方法引用
方法引用是Lambda表达式的一种简化形式,当Lambda表达式仅调用一个已存在的方法时,可以使用方法引用。
4.1 方法引用的类型
import java.util.Arrays;
import