Java函数式编程Lambda表达式与StreamAPI实战指南
### Java函数式编程Lambda表达式与StreamAPI实战指南
#### 一、Lambda表达式基础
Lambda表达式是Java 8引入的核心特性,用于简化匿名内部类的写法,使代码更简洁清晰。
基本语法:
```java
(parameters) -> expression
(parameters) -> { statements; }
```
示例:
```java
// 传统匿名内部类
Runnable task1 = new Runnable() {
@Override
public void run() {
System.out.println(Hello World);
}
};
// Lambda表达式
Runnable task2 = () -> System.out.println(Hello World);
// 带参数的Lambda
Comparator comparator = (s1, s2) -> s1.compareTo(s2);
```
#### 二、函数式接口
函数式接口是只包含一个抽象方法的接口,可以使用`@FunctionalInterface`注解标记。
常用函数式接口:
- `Function`:接受T类型参数,返回R类型结果
- `Consumer`:接受T类型参数,无返回值
- `Supplier`:无参数,返回T类型结果
- `Predicate`:接受T类型参数,返回boolean结果
示例:
```java
// Predicate示例
Predicate isEmpty = s -> s == null || s.trim().isEmpty();
System.out.println(isEmpty.test()); // true
// Function示例
Function stringToInt = Integer::parseInt;
Integer result = stringToInt.apply(123);
```
#### 三、方法引用
方法引用是Lambda表达式的简化写法,有四种形式:
1. 静态方法引用:`ClassName::staticMethod`
2. 实例方法引用:`instance::method`
3. 特定类型的任意对象方法引用:`ClassName::method`
4. 构造器引用:`ClassName::new`
示例:
```java
// 静态方法引用
List numbers = Arrays.asList(1, 2, 3);
numbers.stream()
.map(Integer::parseInt)
.forEach(System.out::println);
// 构造器引用
Supplier> listSupplier = ArrayList::new;
List newList = listSupplier.get();
```
#### 四、Stream API核心操作
Stream API提供对集合数据的函数式处理,支持顺序和并行处理。
创建Stream:
```java
// 从集合创建
List list = Arrays.asList(a, b, c);
Stream stream1 = list.stream();
// 从数组创建
String[] array = {a, b, c};
Stream stream2 = Arrays.stream(array);
// 使用Stream.of
Stream stream3 = Stream.of(a, b, c);
```
#### 五、Stream中间操作
中间操作返回新的Stream,可以链式调用。
常用中间操作:
```java
List names = Arrays.asList(Alice, Bob, Charlie, David);
// filter - 过滤
List longNames = names.stream()
.filter(name -> name.length() > 4)
.collect(Collectors.toList());
// map - 转换
List nameLengths = names.stream()
.map(String::length)
.collect(Collectors.toList());
// sorted - 排序
List sortedNames = names.stream()
.sorted()
.collect(Collectors.toList());
// distinct - 去重
List uniqueNames = names.stream()
.distinct()
.collect(Collectors.toList());
```
#### 六、Stream终端操作
终端操作会触发Stream的处理并返回结果。
常用终端操作:
```java
List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// forEach - 遍历
numbers.stream()
.filter(n -> n % 2 == 0)
.forEach(System.out::println);
// collect - 收集结果
List evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
// reduce - 归约
Integer sum = numbers.stream()
.reduce(0, Integer::sum);
// count - 计数
long count = numbers.stream().count();
// anyMatch/allMatch/noneMatch - 匹配检查
boolean hasEven = numbers.stream().anyMatch(n -> n % 2 == 0);
```
#### 七、实战案例
案例1:员工数据处理
```java
class Employee {
private String name;
private String department;
private double salary;
private int age;
// 构造方法、getter、setter省略
}
List employees = Arrays.asList(
new Employee(Alice, IT, 5000, 25),
new Employee(Bob, HR, 4000, 30),
new Employee(Charlie, IT, 6000, 35)
);
// 按部门分组,计算平均薪资
Map avgSalaryByDept = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.averagingDouble(Employee::getSalary)
));
// 找出IT部门薪资最高的员工
Optional highestPaidInIT = employees.stream()
.filter(e -> IT.equals(e.getDepartment()))
.max(Comparator.comparingDouble(Employee::getSalary));
// 按年龄排序,获取前3名
List top3ByAge = employees.stream()
.sorted(Comparator.comparingInt(Employee::getAge).reversed())
.limit(3)
.collect(Collectors.toList());
```
案例2:复杂数据处理
```java
List sentences = Arrays.asList(
Java is a programming language,
Stream API makes collection processing easy,
Lambda expressions simplify code
);
// 统计所有句子中不同单词的数量
long uniqueWordCount = sentences.stream()
.flatMap(sentence -> Arrays.stream(sentence.split( )))
.map(String::toLowerCase)
.distinct()
.count();
// 按单词长度分组
Map> wordsByLength = sentences.stream()
.flatMap(sentence -> Arrays.stream(sentence.split( )))
.collect(Collectors.groupingBy(String::length));
// 找出出现频率最高的单词
Optional mostFrequentWord = sentences.stream()
.flatMap(sentence -> Arrays.stream(sentence.split( )))
.collect(Collectors.groupingBy(String::toLowerCase, Collectors.counting()))
.entrySet().stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey);
```
#### 八、并行Stream
利用多核处理器提高处理效率。
```java
List largeList = // 大量数据
// 顺序处理
long startTime = System.currentTimeMillis();
long count1 = largeList.stream().filter(n -> n % 2 == 0).count();
long sequentialTime = System.currentTimeMillis() - startTime;
// 并行处理
startTime = System.currentTimeMillis();
long count2 = largeList.parallelStream().filter(n -> n % 2 == 0).count();
long parallelTime = System.currentTimeMillis() - startTime;
System.out.println(顺序处理时间: + sequentialTime + ms);
System.out.println(并行处理时间: + parallelTime + ms);
```
#### 九、最佳实践
1. 保持Lambda简洁:复杂的逻辑应提取为方法
2. 避免副作用:不要在Lambda中修改外部状态
3. 使用方法引用:使代码更清晰
4. 注意性能:小数据集使用顺序Stream,大数据集考虑并行
5. 合理使用Optional:避免空指针异常
#### 十、常见陷阱
1. 在Lambda中修改外部变量:只能使用final或等效final的变量
2. 过度使用并行Stream:注意线程安全和性能开销
3. 忽略异常处理:在Lambda中妥善处理受检异常
通过掌握Lambda表达式和Stream API,可以显著提升Java代码的可读性和开发效率,实现更加函数式的编程风格。
更多推荐


所有评论(0)