Java Lambda表达式详解:函数式编程入门
Java Lambda表达式详解:函数式编程入门
概述
Lambda表达式是Java 8引入的特性,它提供了一种简洁的方式来表示匿名函数。Lambda表达式支持函数式编程风格,使代码更简洁、更易读。
1. Lambda表达式基础
语法
// 基本语法
(参数列表) -> { 方法体 }
// 单参数可省略括号
参数 -> { 方法体 }
// 单语句可省略大括号和return
(参数) -> 表达式
示例
import java.util.Arrays;
import java.util.List;
import java.util.function.*;
public class LambdaBasicExample {
public static void main(String[] args) {
// 1. 无参数Lambda
Runnable runnable = () -> System.out.println("Hello Lambda!");
runnable.run();
// 2. 单参数Lambda
Consumer<String> printer = s -> System.out.println(s);
printer.accept("Hello Consumer!");
// 3. 多参数Lambda
BinaryOperator<Integer> add = (a, b) -> a + b;
System.out.println("Add: " + add.apply(5, 3));
// 4. 多行Lambda
Function<String, Integer> stringLength = s -> {
int length = s.length();
System.out.println("计算长度");
return length;
};
System.out.println("Length: " + stringLength.apply("Hello"));
}
}
2. 函数式接口
import java.util.function.*;
public class FunctionalInterfaceExample {
public static void main(String[] args) {
// Predicate<T>:断言,返回boolean
Predicate<Integer> isEven = n -> n % 2 == 0;
System.out.println("4是偶数: " + isEven.test(4));
System.out.println("5是偶数: " + isEven.test(5));
// Function<T, R>:转换
Function<String, Integer> toLength = String::length;
System.out.println("Hello长度: " + toLength.apply("Hello"));
// Consumer<T>:消费
Consumer<String> shout = s -> System.out.println(s.toUpperCase());
shout.accept("hello world");
// Supplier<T>:提供
Supplier<Double> randomValue = Math::random;
System.out.println("随机数: " + randomValue.get());
// UnaryOperator<T>:一元操作
UnaryOperator<String> exclaim = s -> s + "!";
System.out.println(exclaim.apply("Hello"));
// BinaryOperator<T>:二元操作
BinaryOperator<Integer> multiply = (a, b) -> a * b;
System.out.println("3 * 4 = " + multiply.apply(3, 4));
}
}
3. 方法引用
import java.util.Arrays;
import java.util.List;
import java.util.function.*;
public class MethodReferenceExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Charlie", "Alice", "Bob", "David");
// 1. 静态方法引用:ClassName::staticMethod
names.forEach(System.out::println);
// 2. 实例方法引用:instance::method
String str = "Hello World";
Function<String, String> toUpperCase = str::toUpperCase;
System.out.println(toUpperCase.apply("hello"));
// 3. 对象方法引用:ClassName::method
Function<String, Integer> length = String::length;
System.out.println("Hello长度: " + length.apply("Hello"));
// 4. 构造方法引用:ClassName::new
Supplier<List<String>> listFactory = ArrayList::new;
List<String> newList = listFactory.get();
System.out.println("新列表: " + newList);
// 排序示例
names.sort(String::compareToIgnoreCase);
System.out.println("排序后: " + names);
}
}
4. Lambda与集合操作
import java.util.*;
import java.util.stream.*;
public class LambdaWithCollections {
public static void main(String[] args) {
List<String> names = Arrays.asList("Charlie", "Alice", "Bob", "David", "Eve");
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// forEach
System.out.print("Names: ");
names.forEach(name -> System.out.print(name + " "));
System.out.println();
// filter
List<String> filtered = names.stream()
.filter(name -> name.length() > 3)
.collect(Collectors.toList());
System.out.println("Length > 3: " + filtered);
// map
List<Integer> lengths = names.stream()
.map(String::length)
.collect(Collectors.toList());
System.out.println("Lengths: " + lengths);
// sorted
List<String> sorted = names.stream()
.sorted()
.collect(Collectors.toList());
System.out.println("Sorted: " + sorted);
// reduce
int sum = numbers.stream()
.reduce(0, Integer::sum);
System.out.println("Sum: " + sum);
// anyMatch
boolean hasEven = numbers.stream()
.anyMatch(n -> n % 2 == 0);
System.out.println("Has even: " + hasEven);
// allMatch
boolean allPositive = numbers.stream()
.allMatch(n -> n > 0);
System.out.println("All positive: " + allPositive);
// collect to map
Map<String, Integer> nameLengths = names.stream()
.collect(Collectors.toMap(
name -> name,
String::length
));
System.out.println("Name lengths: " + nameLengths);
}
}
5. 高级Lambda用法
闭包
import java.util.function.*;
public class ClosureExample {
public static Function<Integer, Integer> createAdder(int x) {
return y -> x + y; // x是闭包变量
}
public static void main(String[] args) {
Function<Integer, Integer> add5 = createAdder(5);
Function<Integer, Integer> add10 = createAdder(10);
System.out.println("5 + 3 = " + add5.apply(3));
System.out.println("10 + 3 = " + add10.apply(3));
}
}
组合
import java.util.function.*;
public class CompositionExample {
public static void main(String[] args) {
Function<Integer, Integer> doubleIt = x -> x * 2;
Function<Integer, Integer> addThree = x -> x + 3;
// 组合函数
Function<Integer, Integer> doubleThenAdd = doubleIt.andThen(addThree);
Function<Integer, Integer> addThenDouble = doubleIt.compose(addThree);
System.out.println("doubleThenAdd(5): " + doubleThenAdd.apply(5)); // 13
System.out.println("addThenDouble(5): " + addThenDouble.apply(5)); // 16
// 条件组合
Predicate<Integer> isPositive = n -> n > 0;
Predicate<Integer> isEven = n -> n % 2 == 0;
Predicate<Integer> isPositiveAndEven = isPositive.and(isEven);
Predicate<Integer> isPositiveOrEven = isPositive.or(isEven);
System.out.println("5 is positive and even: " + isPositiveAndEven.test(5));
System.out.println("5 is positive or even: " + isPositiveOrEven.test(5));
}
}
6. 实际应用示例
数据处理管道
import java.util.*;
import java.util.stream.*;
public class DataProcessingPipeline {
static class Person {
String name;
int age;
String city;
Person(String name, int age, String city) {
this.name = name;
this.age = age;
this.city = city;
}
@Override
public String toString() {
return name + "(" + age + ")";
}
}
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 25, "New York"),
new Person("Bob", 30, "London"),
new Person("Charlie", 35, "New York"),
new Person("David", 28, "Paris"),
new Person("Eve", 22, "London")
);
// 数据处理管道
List<String> result = people.stream()
.filter(p -> p.age >= 25) // 筛选年龄>=25
.filter(p -> p.city.equals("New York")) // 筛选纽约
.map(p -> p.name) // 提取姓名
.sorted() // 排序
.collect(Collectors.toList()); // 收集结果
System.out.println("Result: " + result);
// 统计信息
IntSummaryStatistics stats = people.stream()
.mapToInt(p -> p.age)
.summaryStatistics();
System.out.println("Average age: " + stats.getAverage());
System.out.println("Max age: " + stats.getMax());
System.out.println("Min age: " + stats.getMin());
// 按城市分组
Map<String, List<Person>> byCity = people.stream()
.collect(Collectors.groupingBy(p -> p.city));
System.out.println("By city: " + byCity);
}
}
7. 最佳实践
- 保持简洁:Lambda表达式应该简短易读
- 使用方法引用:当Lambda只是调用现有方法时
- 避免副作用:Lambda应该是纯函数
- 选择合适的函数式接口:根据需求选择Predicate、Function等
- 使用流操作:集合操作优先使用Stream API
总结
Lambda表达式是Java 8引入的重要特性,它支持函数式编程风格,使代码更简洁、更易读。掌握Lambda表达式的语法、函数式接口和流操作,是现代Java编程的重要技能。