当前位置: 首页 > article >正文

【Java入门指南 Day11:Lambda表达式与Stream API】

一、Lambda表达式基础

Lambda表达式是Java 8引入的一个重要特性,它让我们可以将行为像数据一样传递。可以把它理解为一种简洁的、匿名的函数定义方式。

Lambda表达式语法

// 基本语法: (参数) -> {表达式}

// 1. 无参数
Runnable r = () -> System.out.println("Hello");

// 2. 单个参数(可以省略括号)
Consumer<String> consumer = str -> System.out.println(str);

// 3. 多个参数
BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b;

// 4. 带代码块
Comparator<String> c = (s1, s2) -> {
    System.out.println("Comparing");
    return s1.compareTo(s2);
};

Lambda表达式的类型推断

// Java编译器可以根据上下文推断Lambda表达式的参数类型
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

// 不需要指定String类型
names.sort((x, y) -> x.compareToIgnoreCase(y));

二、函数式接口

函数式接口是只有一个抽象方法的接口,可以用@FunctionalInterface注解标记。

常用函数式接口

// 1. Consumer:接收一个参数,不返回结果
Consumer<String> printer = s -> System.out.println(s);

// 2. Function:接收一个参数,返回一个结果
Function<String, Integer> lengthFunc = s -> s.length();

// 3. Predicate:接收一个参数,返回布尔值
Predicate<String> isEmpty = s -> s.isEmpty();

// 4. Supplier:不接收参数,返回一个结果
Supplier<Double> random = () -> Math.random();

自定义函数式接口

@FunctionalInterface
interface MathOperation {
    int operate(int a, int b);
    
    // 可以有默认方法
    default int operateDouble(int a, int b) {
        return operate(a, b) * 2;
    }
}

// 使用自定义函数式接口
MathOperation add = (a, b) -> a + b;
MathOperation multiply = (a, b) -> a * b;

三、Stream API详解

Stream API提供了一种声明式的方式来处理数据集合。

Stream操作基础

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

// 创建流
Stream<String> stream = names.stream();

// 链式操作
List<String> filteredNames = names.stream()
    .filter(name -> name.length() > 4)    // 过滤
    .map(String::toUpperCase)             // 转换
    .sorted()                             // 排序
    .collect(Collectors.toList());        // 收集结果

常用Stream操作

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

// 1. 筛选和切片
List<Integer> evenNumbers = numbers.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());

// 2. 映射
List<String> numberStrings = numbers.stream()
    .map(String::valueOf)
    .collect(Collectors.toList());

// 3. 归约
int sum = numbers.stream()
    .reduce(0, Integer::sum);

// 4. 收集
Map<Boolean, List<Integer>> evenOddMap = numbers.stream()
    .collect(Collectors.groupingBy(n -> n % 2 == 0));

四、并行流和性能优化

并行流使用

// 将顺序流转换为并行流
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.parallelStream()
    .mapToInt(Integer::intValue)
    .sum();

// 复杂操作的并行处理
List<String> processedData = bigList.parallelStream()
    .filter(item -> item != null)
    .map(item -> processItem(item))
    .collect(Collectors.toList());

性能优化建议

// 1. 避免在并行流中使用有状态操作
// 不好的例子
AtomicInteger counter = new AtomicInteger();
stream.parallel().forEach(item -> counter.incrementAndGet());

// 2. 使用适当的数据结构
// 好的例子
ArrayList<Integer> list = new ArrayList<>();
// 不好的例子
LinkedList<Integer> linkedList = new LinkedList<>();

五、Optional类使用

Optional类是用来防止空指针异常的容器对象。

// 创建Optional对象
Optional<String> optional = Optional.of("Hello");
Optional<String> empty = Optional.empty();
Optional<String> nullable = Optional.ofNullable(null);

// 安全地获取值
String result = optional.orElse("Default");
String result2 = optional.orElseGet(() -> "Computed Default");
String result3 = optional.orElseThrow(() -> new RuntimeException("Value not present"));

// 链式操作
Optional<String> name = Optional.ofNullable(user)
    .map(User::getAddress)
    .map(Address::getCity)
    .map(City::getName);

最佳实践建议 💡

  1. Lambda表达式
    • 保持简短和清晰
    • 避免在Lambda中使用复杂的逻辑
    • 适当使用方法引用
  2. Stream操作
    • 使用合适的终端操作
    • 注意流操作的顺序
    • 避免过度使用Stream
  3. 并行流
    • 在适当的场景使用并行流
    • 注意数据量和计算复杂度
    • 考虑线程安全性

常见陷阱提醒 ⚠️

  1. Lambda陷阱
// 错误:在Lambda中修改外部变量
int sum = 0;
list.forEach(i -> sum += i);  // 编译错误
  1. Stream陷阱
// 错误:重复使用Stream
Stream<String> stream = list.stream();
stream.forEach(System.out::println);
stream.forEach(System.out::println);  // IllegalStateException
  1. Optional陷阱
// 错误:不恰当的Optional使用
Optional<String> optional = Optional.ofNullable(str);
if (optional.isPresent()) {  // 不推荐
    return optional.get();
} else {
    return "default";
}

// 正确方式
return optional.orElse("default");

函数式编程特性大大提升了Java的表达能力和代码简洁性。合理使用这些特性可以写出更加优雅和高效的代码。


http://www.kler.cn/a/442843.html

相关文章:

  • Spring中三级缓存详细讲解
  • Cline(原Claude Dev)开源的IDE AI插件,如何搭配OpenRouter实现cursor功能,Cline怎么使用
  • 【Linux】网络层
  • 《深度学习模型在鸿蒙分布式框架下的跨设备高效之旅》
  • 系统思考—因果关系
  • https原理
  • 8.2 分库分表简介
  • Java创建对象有几种方式?
  • 理解并使用 sysdig
  • ubuntu监测硬盘状态
  • 图像分割数据集石头rock分割数据集labelme格式2602张3类别
  • Leetcode 208实现Trie树前缀
  • iOS 核心动画
  • 【深入理解ApacheTomcat】
  • 数据结构和算法-06线段树-01
  • DOA估计算法——ESPRIT算法
  • mysql,创建数据库和用户授权核心语句
  • 使用 ts-node插件运行ts
  • C++的诗行:类与对象(中)
  • 关于IP代理API,我应该了解哪些功能特性?以及如何安全有效地使用它来隐藏我的网络位置?
  • 通过Canvas获得视频某一帧
  • Myabits的执行过程
  • Eureka控制中心:微服务控制的极速上手指南
  • WPF+MVVM案例实战与特效(四十一)-WPF文本到几何路径转换的艺术:轻松实现自定义字体路径生成
  • Linux: 通过/proc/pid/stack查看程序卡在内核的什么地方
  • Python 实现炸弹人游戏