2026/2/19 23:57:22
网站建设
项目流程
网站建设需要哪些成本,知名企业网站规划书,wordpress free cdn,怎么提高自己网站的知名度在 Java 8 之后#xff0c;Stream API 已经成为日常开发中不可或缺的工具。
但很多人对 Stream 的理解#xff0c;仍停留在 filter map collect。
本文结合真实业务场景#xff0c;总结 Stream API 的正确使用方式、常见误区和进阶技巧。一、为什么要用 Stream API直奔主题…在Java 8之后Stream API 已经成为日常开发中不可或缺的工具。但很多人对 Stream 的理解仍停留在 filter map collect。本文结合真实业务场景总结 Stream API 的正确使用方式、常见误区和进阶技巧。一、为什么要用 Stream API直奔主题嗷 ~ 我们首先结合一组代码来体会一下不用 Stream API 和使用 Stream API 带给我们的便捷。下图左方代码是没有使用 Stream API 的代码我们通过增强 for 循环对 List 中的元素进行过滤分离出其中年龄 18 的用户信息右图则是使用了 Stream API 的代码看出来了吗代码的简洁程度、可读性即使没有用过 Stream API你是不是也能大致推断出右侧代码的含义呢大致说明Stream 的核心价值✅声明式编程关注做什么而不是怎么做✅链式调用可读性强✅天然支持并行流✅减少临时变量和样板代码二、Stream API 的整体执行流程重点首先我们需要明确的是 Stream 并不是集合而是对数据的一次性流水线处理。其大致结构是数据源 → 中间操作0~N→ 终止操作1 个举个例子 ~users.stream() // 数据源 .filter(u - u.isValid()) // 中间操作 .map(User::getName) // 中间操作 .collect(Collectors.toList()); // 终止操作⚠️注意没有终止操作Stream 不会执行三、常用操作实战(一)、常见中间操作1️⃣ filter过滤最常用对字段进行过滤是我们使用 Stream API 最为常见的需求。如果其中需要对字段进行判空请注意空值过滤一定要放在最前面、复杂条件可抽成方法提高可读性。如下 ~list.stream() .filter(Objects::nonNull) .filter(e - e.getStatus() 1) .collect(Collectors.toList());2️⃣map对象转化典型场景Entity → DTO、提取某个字段、类型转换。ListLong ids users.stream() .map(User::getId) .collect(Collectors.toList());3️⃣ flatMap扁平化和上述 map 的区别map 是一对一flatMap 则是一对多并拉平详见代码ListString allTags articles.stream() .flatMap(a - a.getTags().stream()) .distinct() .collect(Collectors.toList());(二)、常见终止操作1️⃣ collect最常见将经过处理的数据收集起来可以转成 List, Set, 也可以转成 Map如下// 1. 转 List Collectors.toList(); // 2. 转 Set Collectors.toSet(); // 3. 转 Map (注意可能出现的重复 key) MapLong, User map users.stream() .collect(Collectors.toMap( User::getId, Function.identity(), (a, b) - a // 冲突时保留第一个 ));2️⃣ forEach vs forEachOrdered并行流中 forEach 不保证顺序如果需要顺序则需要用forEachOrderedstream.forEach(System.out::println); stream.forEachOrdered(System.out::println);3️⃣ anyMatch / allMatch / noneMatch这几个非常适合做校验逻辑如boolean hasInvalid users.stream() .anyMatch(u - !u.isValid());(三)、常见联合操作1️⃣ 排序list.stream() .sorted(Comparator.comparing(User::getAge).reversed()) .collect(Collectors.toList());2️⃣ 去重按字段ListUser distinct list.stream() .collect(Collectors.collectingAndThen( Collectors.toMap(User::getId, u - u, (a, b) - a), m - new ArrayList(m.values()) ));3️⃣ 模糊分页仅适合小数据量list.stream() .skip((page - 1) * size) .limit(size) .collect(Collectors.toList());四、Stream API 的常见坑❌ Stream 不能复用每次使用都需要重新 stream() 嗷 ~StreamUser stream users.stream(); stream.count(); stream.collect(...); // 抛异常❌ 在 Stream 中修改外部变量Stream 是函数式风格强调无副作用 ~int sum 0; list.stream().forEach(e - sum e); // 编译失败❌ 过度使用 Stream有些逻辑用 for 循环更清晰经验法则是简单遍历for数据转换、过滤、聚合Stream❌ 并行流 parallelStream 真的快吗list.parallelStream().forEach(...)不一定快甚至可能更慢。并行流适用于数据量大、无共享状态、CPU 密集型、单次操作耗时较长的场景而不适合IO 操作、数据量小、有锁 / 有副作用的场景嗷 ~总结一下下班咯 ~Stream API不是为了炫技而是为了让代码更清晰。用得好它是利器用不好就是灾难。 建议“能用 Stream 简化的地方用 Stream不能就老老实实写 for”