java打卡学习2:Stream高级与Optional

Stream 高级操作

Stream API 提供了丰富的中间操作和终端操作,用于处理集合数据。以下是一些高级用法:

过滤与映射

java 复制代码
list.stream()
    .filter(e -> e.getAge() > 18)  // 过滤年龄大于18的元素
    .map(Person::getName)          // 转换为姓名列表
    .collect(Collectors.toList());

扁平化处理

java 复制代码
List<List<String>> nestedList = ...;
nestedList.stream()
          .flatMap(Collection::stream)  // 扁平化为单一流
          .distinct()                   // 去重
          .forEach(System.out::println);

分组与分区

java 复制代码
Map<String, List<Person>> byCity = 
    people.stream()
          .collect(Collectors.groupingBy(Person::getCity));

Map<Boolean, List<Person>> partitioned = 
    people.stream()
          .collect(Collectors.partitioningBy(p -> p.getAge() > 30));

Optional 深度用法

Optional 用于避免空指针异常,提供更优雅的null处理方式。

创建Optional

java 复制代码
Optional<String> emptyOpt = Optional.empty();
Optional<String> ofOpt = Optional.of("value");  // 值不能为null
Optional<String> nullableOpt = Optional.ofNullable(nullableValue);

链式操作

java 复制代码
String result = Optional.ofNullable(user)
    .map(User::getAddress)
    .map(Address::getStreet)
    .orElse("default street");

条件处理

java 复制代码
optionalValue.ifPresent(v -> System.out.println("Found: " + v));

optionalValue.orElseThrow(() -> new RuntimeException("Value not present"));

结合Stream使用

java 复制代码
List<String> names = users.stream()
    .map(User::getName)
    .flatMap(Optional::stream)  // Java9+ 自动解包
    .collect(Collectors.toList());

性能注意事项

  • 避免在循环中创建Stream
  • 优先使用基本类型特化流(IntStream等)
  • 并行流仅在数据量大且无状态操作时使用

collect收集器

Collectors是Java 8中StreamAPI的核心工具类,用于将流中的元素聚合为集合或其他形式的结果。常用方法包括:

  • toList()/toSet():转换为List或Set

    java 复制代码
    List<String> list = stream.collect(Collectors.toList());
  • toMap():转换为Map,需指定键和值的提取函数

    java 复制代码
    Map<Integer, String> map = stream.collect(Collectors.toMap(Person::getId, Person::getName));
  • groupingBy():按条件分组

    java 复制代码
    Map<String, List<Person>> group = stream.collect(Collectors.groupingBy(Person::getDepartment));
  • joining():拼接字符串

    java 复制代码
    String joined = stream.collect(Collectors.joining(", "));

方法引用

方法引用是Lambda表达式的简写形式,通过::符号引用已有方法。分为四种类型:

  1. 静态方法引用

    java 复制代码
    Function<String, Integer> parser = Integer::parseInt;
  2. 实例方法引用

    java 复制代码
    List<String> list = Arrays.asList("A", "B");
    list.forEach(System.out::println);
  3. 对象方法引用

    java 复制代码
    String str = "test";
    Supplier<Integer> lengthSupplier = str::length;
  4. 构造方法引用

    java 复制代码
    Supplier<List<String>> listSupplier = ArrayList::new;

Optional空值处理

Optional用于避免NullPointerException,提供链式空值检查。核心方法:

  • ofNullable():包装可能为null的值

    java 复制代码
    Optional<String> opt = Optional.ofNullable(getNullableString());
  • orElse():提供默认值

    java 复制代码
    String value = opt.orElse("default");
  • orElseGet():延迟计算默认值

    java 复制代码
    String value = opt.orElseGet(() -> computeFallback());
  • map()flatMap():链式转换

    java 复制代码
    Optional<Integer> length = opt.map(String::length);

今日练习

分组统计的实现方法

使用SQL进行分组统计时,GROUP BY子句是关键。例如统计每个部门的员工数量:

sql 复制代码
SELECT department, COUNT(*) as employee_count 
FROM employees 
GROUP BY department;

在Java中利用Stream API进行分组统计:

java 复制代码
Map<String, Long> countByDepartment = employees.stream()
    .collect(Collectors.groupingBy(Employee::getDepartment, Collectors.counting()));

空指针优化的处理策略

Java中Optional类可以优雅处理空指针:

java 复制代码
Optional.ofNullable(obj)
    .map(Object::toString)
    .orElse("default");

使用Objects工具类进行空校验:

java 复制代码
String value = Objects.requireNonNullElse(input, "default");

数据库查询的空值处理

SQL中使用COALESCE函数处理空值:

sql 复制代码
SELECT COALESCE(column_name, 'N/A') FROM table;

MySQL的IFNULL函数:

sql 复制代码
SELECT IFNULL(column_name, 0) FROM table;

前端空值展示优化

JavaScript可选链操作符:

javascript 复制代码
const name = user?.profile?.name ?? 'Anonymous';

Vue/React中使用条件渲染:

jsx 复制代码
{user && <Profile data={user.profile} />}

日志记录中的空指针防护

日志输出前进行空校验:

java 复制代码
log.debug("User info: {}", Optional.ofNullable(user).map(User::toString).orElse("[null]"));

使用String.format时添加防护:

java 复制代码
String.format("Value: %s", obj != null ? obj : "null");
相关推荐
俄城杜小帅2 小时前
C++线程异步和wpf中比较
java·c++·wpf
umeelove352 小时前
Springboot的jak安装与配置教程
java·spring boot·后端
The_Ticker2 小时前
日股实时行情接口使用指南
java·经验分享·笔记·python·算法·区块链
试试勇气2 小时前
Linux学习笔记(十九)--生产消费模型与线程安全
java·笔记·学习
jiayong232 小时前
0基础学习VUE3 第 3 课:任务页怎么把列表、筛选、表单、弹窗串起来
前端·javascript·学习
凌波粒2 小时前
LeetCode--24.两两交换链表中的节点(链表)
java·算法·leetcode·链表
pupudawang2 小时前
Spring Boot 各种事务操作实战(自动回滚、手动回滚、部分回滚)
java·数据库·spring boot
arvin_xiaoting2 小时前
OpenClaw学习总结_II_频道系统_4:Slack集成详解
前端·学习·自动化·llm·ai agent·飞书机器人·openclaw
C++chaofan2 小时前
RPC框架SPI机制深度解析
java·网络·后端·网络协议·rpc·spi·序列化器