本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!
首先分享之前的所有文章 , 欢迎点赞收藏转发三连下次一定 >>>> 😜😜😜
文章合集 : 🎁 juejin.cn/post/694164…
Github : 👉 github.com/black-ant
CASE 国内备份 : 👉 gitee.com/antblack/ca…
一 .前言
Java 流这个特性已经出来很久了 , 可以大大的减少我们的代码 , 而且并行处理可以在某些场景下使用多个处理器核心可以大大的提高性能.
不过 Stream 语法新手使用起来还是会有一定的难度 , 这一篇文档由浅到深看一下这个特性.
这是开篇 , 只记录之前梳理的用法 , 下一篇来看源码 , 记得收藏!!!!!
Stream 的特点
- Stream 不是集合 , 也不是数据结构 , 不可以保存数据
- Stream 有点类似于高级 的 Iterator , 可以用于算法和计算
- 不同于迭代器 , Stream 可以并行化操作 , 数据被分为很多段 , 在不同的线程中进行处理
- 数据源、零个或多个中间操作 ( intermediate ) 以及零个或一个终端操作 (terminal )
- 所有中间操作都是惰性的 , 在管道开始工作之前,任何操作都不会产生任何效果
- 终端操作有点像水龙头 , 开启了水龙头后 , 水才会流动 , 中间操作才会执行
二. 基础知识
2.1 结构运算
2.1.1 双冒号运算
双冒号运算就是将方法当成参数传递给需要的方法 ( Stream ) , 即为方法引用
案例一 : 基础用法
1 | java复制代码x -> System.out.println(x) |
案例二 : 复杂用法
1 | java复制代码for (String item: list) { |
2.2 流的创建
2.2.1 集合和数组工具
基础案例
1 | java复制代码// Collection 工具 |
创建一个整数流
1 | java复制代码IntStream.rangeClosed(1, 100).reduce(0, Integer::sum); |
创建一个并行流
1 | java复制代码// API : |
数组创建流
1 | java复制代码Arrays.stream(intArray).reduce(0, Integer::sum); |
合并流
1 | JAVA复制代码// API : 组合2个 Streams |
其他的案例
1 | java复制代码// 静态工厂 |
补充
分割流案例
2.3 流的操作
一个流可以有多个 intermediate 操作 , 和一个 Terminal 操作 , 当 Terminal 执行完成后, 流就结束了
2.3.1 流的 Intermediate 操作
map : 元素映射
1 | java复制代码// API : |
flatMap
1 | java复制代码// flatMap 返回的是一个 Stream |
mapToXXX
1 | java复制代码// API : |
filter : 过滤 ,通过过滤的元素被流下来生成新的 stream
1 | java复制代码// Predicate 是一个函数式接口 |
distinct : 去重
1 | java复制代码nums.stream().filter(num -> num % 2 == 0).distinct().collect(Collectors.toList()); |
sorted : 排序
1 | java复制代码// 自定义排序方式 |
peek
1 | java复制代码// API : 可以用于调试 ,主要在流通过管道中的某个点时进行拦截 |
limit : 限制
1 | java复制代码// API : 截断流的数量 , 可以看到还是返回一个流 |
skip : 跳过
1 | java复制代码// API : |
parallel 并行流
1 | java复制代码// API : 返回一个并行的等效流 , 如果已经是并行 ,返回自身 |
sequential : 串行流
1 | java复制代码// API : |
unordered : 无序化
1 | java复制代码// 消除相遇顺序 , 可以提交并行性能 |
2.3.2 流的 Terminal 操作之聚合
foreach : 循环遍历
1 | java复制代码// API : 可以看到 , 这里接受到的是一个 Consumer 函数 |
forEachOrdered : 有序的循环流
1 | java复制代码list.stream().parallel().forEachOrdered(e -> logger.info(e)); |
Array
1 | java复制代码stream.toArray(String[]::new); |
collection
- stream.collect(Collectors.toList()) : toList把流中所有的元素收集到List 中
- stream.collect(Collectors.toCollection(ArrayList::new)): 把流中的元素收集到给定的供应源创建的集合中
- stream.collect(Collectors.toSet()) : 把流中所有的元素保存到Set集合中,删除重复锁
- stream.collect(Collectors.toCollection(Stack::new))
1 | java复制代码// API |
2.3.3 流的 Terminal 操作之运算
min : 返回此流的最小元素
1 | JAVA复制代码// API |
max : 返回此流的最大元素
1 | JAVA复制代码// API |
count : 计算流中的项目数
1 | JAVA复制代码// API : |
reduce
1 | java复制代码 |
2.4 流的 Terminal 操作之搜索
anyMatch:任一元素满足匹配条件
1 | java复制代码// API : Stream 中只要有一个元素符合传入的 predicate,返回 true |
allMatch:所有元素都满足匹配条件
1 | java复制代码// API : Stream 中全部元素符合传入的 predicate,返回 true |
findFirst:返回Stream中的第一个元素
1 | java复制代码// API : 返回一个 Optional 标识第一个元素 |
findAny:返回Stream中的任意个元素
1 | java复制代码// API : findAny不一定返回第一个,而是返回任意一个 , 如果流为空则返回一个空的Optional |
noneMatch:所有元素都不满足匹配条件
1 | java复制代码// API : 当Stream 中没有一个元素符合传入的 predicate,返回 true |
2.5 流的规约
1 | java复制代码// reduce : 对参数化操作后的集合进行进一步操作 |
2.6 流的分组 (Group By)
单级分组
1 | java复制代码// API : |
多级分组
1 | java复制代码// 作用 : |
partitioningBy : 分区 ,区别于groupBy ,分区中只有true , false .
1 | java复制代码// API : 可以看到 , 这里主要是 Predicate 函数 |
三 . 使用深入
3.1 扩展线程池
1 | java复制代码// 全局设置线程池 |
3.2 Debug 处理
四 . 常见案例
案例 一 : 对 List AList 中 每个 元素进行操作转换后生成 另外的类型 C 放入 List BList
1 | java复制代码List<JSONObject> itemjson = new LinkedList<JSONObject>(); |
案例二 : 对 Map 进行循环操作
1 | java复制代码 realmTO.getTemplates().forEach((key, template) -> { |
案例三 : 从大集合中获取小集合
1 | java复制代码 |
案例四 : 分组与分片
1 | java复制代码// 按skuid分组 |
案例五 : 计数与求和
1 | java复制代码// 统计skuId=1的记录数 |
案例 六 :特定用法
1 | java复制代码// 多重分组并排序,先按supplierId分组,再按skuId分组,排序规则,先supplierId后skuId |
案例 七 : 对流进行排序
1 | java复制代码Collections.sort(literals, (final String t, final String t1) -> { |
案例 八 : 对流进行 filter 后 ,获取第一个
1 | java复制代码correlationRules.stream().filter(rule -> anyType != null && anyType.equals(rule.getAnyType())).findFirst() |
案例 九 :一种类型集合转换为另外一种类型集合
1 | java复制代码 List<String> strings = Lists.transform(list, new Function<Integer, String>() { |
案例 十 : 遍历集合并且返回集合
1 | java复制代码return Stream.of(resources).map(resource -> preserveSubpackageName(baseUrlString, resource, path)).collect(Collectors.toList()); |
案例十一 :简单拼接
1 | java复制代码// 拼接成 [x, y, z] 形式 |
案例十二 : 复杂使用
1 | java复制代码buzChanlList.stream() |
案例十三 : 切分集合
1 | java复制代码 List<List<Integer>> splitList = Stream.iterate(0, n -> n + 1).limit(limit).parallel().map(a -> list.stream().skip(a * MAX_NUMBER).limit(MAX_NUMBER).parallel().collect(Collectors.toList())).collect(Collectors.toList()); |
案例十四 : filter 操作
1 | java复制代码collection.stream().filter(person -> "1".equals(person.getGender())).collect(Collectors.toList()) |
总结
流的并行特性在使用得当的情况下可以大大增加效率 , 下一篇我们来看一下源码.
参考
@ www.baeldung.com/intellij-de…
@ Java 8 Stream - Java Stream - JournalDev
@ www.baeldung.com/java-stream…
本文转载自: 掘金