Stream流式使用

Stream流式使用

一、Stream是什么

Stream是支持顺序和并行聚合操作的元素序列。简单来说Stream 就像一条"流水线"------你把数据放上去,经过一道道工序(筛选、加工、转换),最后出来你想要的结果。

二、核心结构:

数据源 → 中间操作(懒执行)→ 终端操作(触发执行)。中间操作只是"记下工序",不会真的跑,直到你调用终端操作(如 collect、forEach)才一次性执行。

java 复制代码
结果 = 数据源.stream()          // 1. 拿到流
        .中间操作1()             // 2. 加工(可多个,懒执行)
        .中间操作2()
        .终端操作();             // 3. 触发执行,出结果

三、Strean的使用

1. 怎么拿到流(源头)

Stream 不能 new,只能从数据源获取:

java 复制代码
list.stream()                    // 集合 → Stream<T>
Arrays.stream(array)             // 数组 → Stream<T>
Stream.of("a", "b", "c")         // 直接创建
IntStream.range(1, 10)           // 生成 1~9 的 int 流
Files.lines(Paths.get("f.txt"))  // 文件每行 → Stream<String>

2. 中间操作(返回 Stream,可链式)

这些方法定义在 Stream / IntStream 等接口上,懒执行:

filter(Predicate) --- 筛选

map(Function) --- 转换

flatMap(Function) --- 转换并"摊平"(比如 List<List> → 一个流)

distinct() --- 去重

sorted() / sorted(Comparator) --- 排序

limit(n) / skip(n) --- 取前 n 个 / 跳过前 n 个

peek(Consumer) --- 偷看每个元素(调试用)

3. 终端操作(触发执行,返回结果)

collect(Collector) --- 收集成 List/Set/Map 等

forEach(Consumer) --- 遍历

count() --- 计数

reduce(...) --- 归约(求和、求积、拼字符串)

anyMatch / allMatch / noneMatch --- 条件判断

findFirst / findAny --- 找元素

min / max --- 最值

sum() / average() --- 只有 IntStream/LongStream/DoubleStream 才有

4.辅助工具

Collectors(java.util.stream.Collectors) 配合 collect 用,是静态工具类,不是流:

java 复制代码
Collectors.toList()               // 收成 List
Collectors.toSet()                // 收成 Set
Collectors.toMap(k, v)            // 收成 Map
Collectors.groupingBy(...)        // 分组 → Map<K, List<T>>
Collectors.joining(",")           // 拼成字符串
Collectors.counting() / summingInt()  // 统计

三、最常见的使用场

  1. 筛选 + 收集(filter + collect) 从用户列表里找出成年人:
java 复制代码
List<User> adults = users.stream()
    .filter(u -> u.getAge() >= 18)
    .collect(Collectors.toList());
  1. 转换(map) 把用户列表转成名字列表:
java 复制代码
List<String> names = users.stream()
    .map(User::getName)
    .collect(Collectors.toList());
对象转另一个对象(如 User → UserDTO):
java 复制代码
List<UserDTO> dtos = users.stream()
    .map(u -> new UserDTO(u.getId(), u.getName()))
    .collect(Collectors.toList());
  1. 筛选 + 转换 + 排序(链式)
java 复制代码
List<String> result = users.stream()
    .filter(u -> u.getAge() >= 18)
    .map(User::getName)
    .sorted()
    .collect(Collectors.toList());
  1. 去重、取前几个、跳过
java 复制代码
list.stream().distinct().collect(Collectors.toList());   // 去重
list.stream().limit(10).collect(Collectors.toList());    // 前 10 个
list.stream().skip(5).collect(Collectors.toList());      // 跳过前 5 个
  1. 判断条件(anyMatch / allMatch / noneMatch)
java 复制代码
boolean hasAdult = users.stream().anyMatch(u -> u.getAge() >= 18);  // 有没有成年人
boolean allAdult = users.stream().allMatch(u -> u.getAge() >= 18);  // 是不是都成年
boolean noChild  = users.stream().noneMatch(u -> u.getAge() < 18);  // 有没有未成年
  1. 找元素(findFirst)
java 复制代码
Optional<User> first = users.stream()
    .filter(u -> u.getAge() > 30)
    .findFirst();

// Optional 要这样取值,避免空指针
String name = first.map(User::getName).orElse("无");
  1. 统计:计数、求和、最值
java 复制代码
long count = users.stream().filter(u -> u.getAge() >= 18).count();

// 求和/平均/最值,用 mapToInt 转成 IntStream 更方便
int totalAge = users.stream().mapToInt(User::getAge).sum();
double avgAge = users.stream().mapToInt(User::getAge).average().orElse(0);
Optional<User> oldest = users.stream().max(Comparator.comparing(User::getAge));
  1. 分组(groupingBy,业务里超常用) 按城市给用户分组:
java 复制代码
Map<String, List<User>> byCity = users.stream()
    .collect(Collectors.groupingBy(User::getCity));

分组后统计每组人数:

java 复制代码
Map<String, Long> cityCount = users.stream()
    .collect(Collectors.groupingBy(User::getCity, Collectors.counting()));
  1. 收成 Map(toMap) id → User 的映射:
rust 复制代码
Map<Long, User> idMap = users.stream()
    .collect(Collectors.toMap(User::getId, u -> u));

// 如果 key 可能重复,要加合并函数,否则会抛异常
Map<String, User> nameMap = users.stream()
    .collect(Collectors.toMap(User::getName, u -> u, (a, b) -> a));
  1. 拼字符串(joining)
java 复制代码
String names = users.stream()
    .map(User::getName)
    .collect(Collectors.joining(", ", "[", "]"));  // 结果形如 [张三, 李四]
  1. 归约(reduce) 求所有年龄之和(也可以用 mapToInt().sum()):
java 复制代码
int sum = users.stream()
    .map(User::getAge)
    .reduce(0, Integer::sum);
  1. flatMap 摊平嵌套集合 比如每个用户有多个订单,想拿到所有订单:
java 复制代码
List<Order> allOrders = users.stream()
    .flatMap(u -> u.getOrders().stream())
    .collect(Collectors.toList());
相关推荐
旋律4141 小时前
List、Set、Map:三个装数据的容器,到底啥区别?怎么遍历?
java·后端
Wang's Blog1 小时前
Java 项目实战: 交友项目 - 回顾和今日内容介绍
java·开发语言·交友
工具派1 小时前
不重写一行老代码:给 Spring Boot 系统加一层 AI 能力
java·人工智能·spring boot
大雄很用心1 小时前
Java 数据结构基础:栈、堆与 Deque
java
牛战士coding1 小时前
用户点了停止生成,上游还在烧 token 吗?取消传播链路拆解
java·人工智能
初心未改HD1 小时前
DSH Skill开发实战:SKILL.md是给LLM看的操作手册,不是给人看的README,踩了4个坑
java·大数据·开发语言
aibo8603081 小时前
基于 Spring Boot 的茶铺管理系统设计与实现
java·spring boot·后端
Wang's Blog2 小时前
Java 项目实战: 交友项目 - SpringData-Mongo 环境搭建和 CRUD
java·开发语言·交友
SunnyDays10112 小时前
Java 操作 PPT 超链接:添加、修改和删除
java·powerpoint·ppt·超链接