《吃透 Java 8 新特性!Lambda、Stream 等核心特性实战详解》
·
第十章:Java 8新特性
10.1 Lambda表达式与函数式编程
1. 基本概念
- 函数式编程思想:将行为作为参数传递
- 核心语法:
(parameters) -> expression (parameters) -> { statements; }
2. 函数式接口
- 定义:仅包含一个抽象方法的接口
- 常用内置接口:
@FunctionalInterfaceFunction<T,R>:输入T输出RPredicate<T>:布尔判断Consumer<T>:消费型操作Supplier<T>:提供型操作BiFunction<T,U,R>:双参数函数
// 示例:函数式接口定义与使用
@FunctionalInterface
interface Calculator {
int calculate(int a, int b);
}
public class LambdaDemo {
public static void main(String[] args) {
// 传统匿名内部类
Calculator add = new Calculator() {
@Override
public int calculate(int a, int b) {
return a + b;
}
};
// Lambda表达式写法
Calculator multiply = (a, b) -> a * b;
System.out.println(add.calculate(3,4)); // 7
System.out.println(multiply.calculate(3,4)); // 12
}
}
3. 实际应用场景
-
集合排序:
List<String> names = Arrays.asList("Java", "Python", "Node.js"); names.sort((a, b) -> a.length() - b.length()); -
事件监听:
button.addActionListener(event -> { System.out.println("按钮被点击"); logEvent(event); }); -
线程启动:
new Thread(() -> { System.out.println("Lambda线程运行"); }).start();
10.2 Stream API与集合操作
1. 核心概念
- 流式处理:声明式操作集合数据
- 操作类型:
- 中间操作:返回新Stream(可链式调用)
- 终端操作:触发实际计算并返回结果
2. 典型操作示例
List<String> languages = Arrays.asList("Java", "Python", "JavaScript", "C++", "Ruby");
// 过滤+转换+聚合
String result = languages.stream()
.filter(s -> s.length() > 5) // 中间操作
.map(String::toUpperCase) // 中间操作
.sorted() // 中间操作
.reduce((a,b) -> a + ", " + b) // 终端操作
.orElse("无结果");
System.out.println(result); // 输出: JAVASCRIPT, PYTHON
3. 并行流处理
// 并行计算总和(适用于大数据集)
int sum = IntStream.range(1, 1_000_000)
.parallel()
.sum();
4. 常用操作汇总表
| 操作类型 | 方法 | 描述 |
|---|---|---|
| 创建 | stream()/parallelStream() |
从集合创建流 |
| 中间 | filter(Predicate) |
过滤元素 |
| 中间 | map(Function) |
转换元素 |
| 中间 | sorted(Comparator) |
排序 |
| 中间 | distinct() |
去重 |
| 终端 | forEach(Consumer) |
遍历 |
| 终端 | collect(Collector) |
聚合 |
| 终端 | reduce(BinaryOperator) |
归约 |
10.3 默认方法与接口扩展
1. 默认方法语法
public interface Formula {
double calculate(int a);
// 默认方法
default double sqrt(int a) {
return Math.sqrt(a);
}
}
2. 多重继承冲突处理
interface A {
default void log() {
System.out.println("A");
}
}
interface B {
default void log() {
System.out.println("B");
}
}
class C implements A, B {
public void log() {
A.super.log(); // 显式指定调用A的实现
}
}
3. 静态方法支持
public interface MathUtils {
static int max(int a, int b) {
return Math.max(a, b);
}
}
// 调用方式
int result = MathUtils.max(10, 20);
4. 设计优势
- 向后兼容:在接口中添加新方法不影响现有实现类
- 代码复用:避免重复实现公共逻辑
- 混合继承:类似其他语言的trait/mixin特性
10.4 新时间日期API(java.time包)
1. 核心类对比
| 类型 | 旧版类 | Java 8新版类 | 特性 |
|---|---|---|---|
| 本地日期 | Date/Calendar | LocalDate |
无时区 |
| 本地时间 | Date/Calendar | LocalTime |
无时区 |
| 日期时间 | Date | LocalDateTime |
无时区 |
| 时区日期时间 | - | ZonedDateTime |
含时区 |
2. 时间操作示例
// 获取当前时间
LocalDateTime now = LocalDateTime.now();
System.out.println(now); // 2025-10-22T14:30:45.123
// 创建指定时间
LocalDate date = LocalDate.of(2025, 10, 22);
LocalTime time = LocalTime.of(14, 30, 45);
LocalDateTime dateTime = LocalDateTime.of(date, time);
// 时间计算
LocalDateTime tomorrow = now.plusDays(1).minusHours(3);
3. 时区处理
// 获取带时区的时间
ZoneId zone = ZoneId.of("Asia/Shanghai");
ZonedDateTime zoned = ZonedDateTime.now(zone);
// 不同时区转换
ZonedDateTime newYorkTime = zoned.withZoneSameInstant(ZoneId.of("America/New_York));
4. 日期格式化
// 自定义格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
String formatted = now.format(formatter); // 2025年10月22日 14:30:45
// 解析字符串为时间
LocalDate parsedDate = LocalDate.parse("2025-10-22", DateTimeFormatter.ISO_DATE);
5. 时间间隔计算
// 计算两个日期间隔
LocalDate startDate = LocalDate.of(2025, 1, 1);
LocalDate endDate = LocalDate.of(2025, 12, 31);
Period period = Period.between(startDate, endDate);
System.out.println(period.getYears() + "年" +
period.getMonths() + "个月" +
period.getDays() + "天");
补充说明
-
Lambda表达式限制:
- 不能访问非final变量
- 不能抛出比函数式接口定义范围更广的异常
-
Stream API性能优化:
- 小数据集避免并行流(创建线程池开销大)
- 使用
unordered()操作提升乱序处理效率
-
时间API设计优势:
- 不可变性:所有操作返回新实例
- 线程安全:无需额外同步
- 更清晰的API设计:方法命名统一
-
迁移建议:
- 新项目应直接使用java.time包
- 旧代码改造时注意Date与LocalDateTime的转换:
Date date = Date.from(Instant.now()); LocalDateTime ldt = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
更多推荐
所有评论(0)