24.Java函数式编程与新特性实战指南

一、函数式编程基础

1.1 什么是函数式编程?

函数式编程是一种编程范式,强调将计算视为函数的求值,避免使用共享状态和可变数据。核心特点:

  • 不可变数据:避免副作用,数据一经创建不可修改
  • 一等公民函数:函数可作为参数和返回值
  • 声明式风格:关注"做什么"而非"怎么做"
  • 高阶函数:函数可操作其他函数

1.2 为什么需要函数式编程?

传统编程问题函数式解决方案
复杂的控制流Stream API简化集合操作
共享可变状态不可变对象和纯函数
冗长的样板代码Lambda表达式和方法引用
并发编程困难无副作用代码天然支持并行

二、Java 8+ 核心新特性

2.1 Lambda表达式

// 传统方式
Runnable r1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello");
    }
};

// Lambda方式
Runnable r2 = () -> System.out.println("Hello");

// 带参数的Lambda
Comparator<String> comparator = (a, b) -> a.compareTo(b);

2.2 函数式接口

// 自定义函数式接口
@FunctionalInterface
public interface Calculator {
    int calculate(int a, int b);
    
    // 默认方法
    default int add(int a, int b) {
        return a + b;
    }
}

// 使用
Calculator calc = (a, b) -> a * b;

2.3 Stream API

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

// 过滤长度大于4的名字,转为大写,取前两个
List<String> result = names.stream()
    .filter(n -> n.length() > 4)
    .map(String::toUpperCase)
    .limit(2)
    .collect(Collectors.toList());

2.4 方法引用

// 构造器引用
Supplier<List<String>> listSupplier = ArrayList::new;

// 静态方法引用
Function<String, Integer> parser = Integer::parseInt;

// 实例方法引用
List<String> names = Arrays.asList("a", "b", "c");
names.forEach(System.out::println);

三、Stream API 深入解析

3.1 中间操作 vs 终端操作

类型操作示例返回值类型
中间操作filter(), map(), sorted()Stream
终端操作forEach(), collect(), count()非Stream类型

3.2 常见Stream操作

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// 过滤和映射
int sum = numbers.stream()
    .filter(n -> n % 2 == 0)     // 过滤偶数
    .mapToInt(n -> n * 2)        // 乘以2
    .sum();                      // 求和

// 并行流
long count = numbers.parallelStream()
    .filter(n -> n > 3)
    .count();

四、Optional类

4.1 解决空指针异常

// 创建Optional
Optional<String> optional = Optional.of("value");
Optional<String> emptyOpt = Optional.empty();
Optional<String> nullableOpt = Optional.ofNullable(null);

// 使用示例
String result = nullableOpt
    .orElse("default");          // 默认值
    // .orElseGet(() -> "default"); // 延迟计算默认值
    // .orElseThrow(() -> new IllegalArgumentException()); // 抛出异常

// 链式操作
optional
    .map(String::toUpperCase)
    .ifPresent(System.out::println);

4.2 实际应用场景

public Optional<User> findUserById(Long id) {
    // 从数据库查询用户
    User user = userRepository.findById(id);
    return Optional.ofNullable(user);
}

// 使用
findUserById(1L)
    .map(User::getName)
    .orElse("Unknown");

五、日期时间API(Java 8+)

5.1 核心类

类名描述
LocalDate不包含时间的日期(如2023-01-01)
LocalTime不包含日期的时间(如14:30:00)
LocalDateTime包含日期和时间
ZonedDateTime带时区的日期时间
Duration表示两个时间点之间的间隔
Period表示两个日期之间的间隔

5.2 常用操作

// 当前日期
LocalDate today = LocalDate.now();

// 指定日期
LocalDate date = LocalDate.of(2023, 5, 1);

// 日期计算
LocalDate tomorrow = today.plusDays(1);
LocalDate previousMonth = today.minusMonths(1);

// 格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String formattedDate = today.format(formatter);

// 解析
LocalDate parsedDate = LocalDate.parse("2023-05-01", formatter);

六、学习要点总结

6.1 核心知识点

  1. Lambda表达式:简化匿名内部类,提高代码可读性
  2. 函数式接口:理解@FunctionalInterface注解和常用接口
  3. Stream API:掌握中间操作和终端操作,处理集合数据
  4. Optional类:有效避免NullPointerException
  5. 日期时间API:线程安全的新日期时间处理方式

6.2 常见问题解答

  1. Q:Lambda表达式和匿名内部类的区别?
    A:Lambda使用函数式接口,不创建新的类;匿名内部类会创建新类

  2. Q:Stream和Collection的区别?
    A:Collection是数据存储,Stream是数据处理;Stream不存储元素

  3. Q:如何选择并行流?
    A:计算密集型且数据量大时使用,否则可能因线程调度开销降低性能

七、练习题

7.1 基础练习

  1. 使用Lambda表达式实现Comparator对字符串列表排序
  2. 使用Stream API过滤出年龄大于18的用户,并计算平均年龄
  3. 使用Optional重构现有代码,消除Null检查

7.2 进阶练习

  1. 使用Stream API实现单词频率统计
  2. 实现一个方法,将List<List<Integer>>展平为一维列表
  3. 使用新日期API计算两个日期之间的工作日天数

八、总结

Java 8+ 引入的函数式编程特性和新API,极大地提升了Java的表达能力和开发效率。通过本章学习,你应该掌握了:

  • 函数式编程的基本概念和优势
  • Lambda表达式和方法引用的使用
  • Stream API处理集合数据的方式
  • Optional类避免空指针异常的最佳实践
  • 新日期时间API的核心类和常用操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

游戏人生的NPC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值