Stream 总结
1 前言
Stream 是 Java 8 中为方便操作集合及其元素而定制的接口,它将要处理的元素集合看作一种流,对流中的元素进行过滤、排序、映射、聚合等操作。使用 Stream API,就好像使用 SQL 中的 select 语句操作数据库,非常快捷高效,一行代码可以实现很多功能。
(1)Stream 操作分类
- 中间操作:每次操作返回一个新的 Stream 对象(主要操作有:filter、map、sorted、peek、distinct、limit、skip 等)。
- 终端操作:每次操作返回一个值或集合,每个流只能进行一次终端操作(主要操作有:forEach、max、min、count、reduce、collect、anyMatch、allMatch、findFirst、findAny 等)。
(2)Stream 特性
- 不存储数据:Stream 不是数据结构,不存储数据,只提供了一系列操作数据的接口。
- 不改变数据源:终端操作后会产生一个新的值或集合。
- 延迟执行:只有调用终端操作时,中间操作才会执行。
在学习 Stream 之前,需要先掌握 Lambda 表达式和 Optional,详见→Lambda 表达式总结、Optional 详解。
2 Stream 的创建
(1)Collection
//Collection 类接口
default Stream<E> stream() //顺序流
default Stream<E> parallelStream() //并行流
//案例
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream(); //获取一个顺序流
Stream<String> parallelStream = list.parallelStream(); //获取一个并行流
说明:List 和 Set 是 Collection 的子类。
(2)Arrays
//Arrays 类接口
public static <T> Stream<T> stream(T[] array)
//案例
Integer[] nums = new Integer[10]{8, 2, 5, 6};
Stream<Integer> stream = Arrays.stream(nums);
(3)Stream
//Stream 类接口
public static<T> Stream<T> of(T... values) //Arrays.stream(values)
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
public static<T> Stream<T> generate(Supplier<T> s)
//案例
Stream<Integer> stream1 = Stream.of(1, 2, 3);
Stream<Integer> stream21 = Stream.iterate(2, x -> x + 2).limit(3); //2 4 6
//斐波那契数列:1 1 2 3 5 8
Stream<Integer> stream22 = Stream.iterate(new int[]{1, 1}, n -> new int[]{n[1], n[0] + n[1]}).limit(6).map(n -> n[0]);
Stream<Double> stream3 = Stream.generate(Math::random).limit(3);
(4)BufferedReader
//BufferedReader 类接口
public Stream<String> lines()
//案例
BufferedReader reader = new BufferedReader(new FileReader("G:\\stream.txt"));
Stream<String> lineStream = reader.lines();
(5)Pattern
//Pattern 类接口
public Stream<String> splitAsStream(final CharSequence input)
//案例
Pattern pattern = Pattern.compile("-");
Stream<String> stream = pattern.splitAsStream("a-b-c-d");
3 Stream 的中间操作
(1)主要接口
//过滤
Stream<T> filter(Predicate<? super T> predicate)
//去重
Stream<T> distinct()
//跳过 n 个元素
Stream<T> skip(long n)
//限制元素个数
Stream<T> limit(long maxSize)
//排序
Stream<T> sorted()
Stream<T> sorted(Comparator<? super T> comparator)
//映射
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
//消费
Stream<T> peek(Consumer<? super T> action)
(2)案例
Stream<Integer> stream = Stream.of(4, 9, 1, 8, 5, 5, 7, 3, 6, 2);
stream.filter(e -> e > 2 && e < 8) //4 5 5 7 3 6
.distinct() //4 5 7 3 6
.skip(1) //5 7 3 6
.limit(3) //5 7 3
.sorted((o1, o2) -> o2 - o1) //7 5 3
.map(e -> e * e) //49 25 9
.forEach(System.out::println);
4 Stream 的终端操作
(1)主要接口
void forEach(Consumer<? super T> action) //遍历所有元素
Optional<T> min(Comparator<? super T> comparator) //最小值
Optional<T> max(Comparator<? super T> comparator) //最大值
long count(); //元素个数
boolean allMatch(Predicate<? super T> predicate) //判断是否全匹配
boolean noneMatch(Predicate<? super T> predicate) //判断是否全不匹配
boolean anyMatch(Predicate<? super T> predicate) //判断是否部分匹配
Optional<T> findFirst() //首元素
Optional<T> findAny() //顺序流时为首元素,并行流为访问的第一个元素
//规约运算,定义运算 o, result = ((((e1 o e2)) o e3) o e4) o ...
Optional<T> reduce(BinaryOperator<T> accumulator)
//规约运算,定义运算 o, result = ((((identity o e1)) o e2) o e3) o ...
T reduce(T identity, BinaryOperator<T> accumulator)
(2)案例
Stream<Integer> stream = Stream.of(1, 2, 3);
Optional<Integer> min = stream.min(Integer::compare); //1
Optional<Integer> max = stream.max(Integer::compare); //3
long count = stream.count(); //3
boolean allMatch = stream.allMatch(e -> e > 2); //false
boolean noneMatch = stream.noneMatch(e -> e > 2); //false
boolean anyMatch = stream.anyMatch(e -> e > 2); //true
Optional<Integer> first = stream.findFirst(); //1
Optional<Integer> any = stream.findAny(); //1
Optional<Integer> sum = stream.reduce(Integer::sum); //6
int result = stream.reduce(1, (e1, e2) -> e1 * e1 - e2 * e2); //7
5 Collectors 库
Collectors 里工具函数需配合 Stream 的 collect() 方法使用,接口如下:
<R, A> R collect(Collector<? super T, A, R> collector)
<R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner)
(1)集合转换
List<User> list = stream.collect(Collectors.toList());
Set<User> set = stream.collect(Collectors.toSet());
Map<Integer, String> map = stream.collect(Collectors.toMap(User::getId, User::getName));
String str = stream.collect(Collectors.joining(",", "(", ")"));
(2)聚合运算
long count = stream.collect(Collectors.counting()); //元素个数
Optional<Integer> min = stream.collect(Collectors.minBy(Integer::compare)); //最小元素
Optional<Integer> max = stream.collect(Collectors.maxBy(Integer::compare)); //最大元素
Integer sumAge = stream.collect(Collectors.summingInt(User::getAge)); //元素总和
Double avg = stream.collect(Collectors.averagingDouble(User::getAge)); //元素平均值
//统计参数
DoubleSummaryStatistics statistics = stream.collect(Collectors.summarizingDouble(User::getAge));
//count: statistics.getCount()
//min: statistics.getMin()
//max: statistics.getMax()
//sum: statistics.getSum()
//average: statistics.getAverage()
(3)规约运算
//规约操作,定义运算 o, result = ((((e1 o e2)) o e3) o e4) o ...
Optional<Integer> sum = stream.collect(Collectors.reducing(Integer::sum));
//规约操作,定义运算 o, result = ((((identity o e1)) o e2) o e3) o ...
Integer result = stream.collect(Collectors.reducing(1, (e1, e2) -> e1 * e1 - e2 * e2));
(4)分组
//单属性分组
Map<Boolean, List<User>> sexMap = stream.collect(Collectors.groupingBy(User::getSex));
//多重分组:先根据性别分组,再根据年龄分组
Map<Boolean, Map<Integer, List<User>>> sexAgeMap = stream.collect(Collectors.groupingBy(User::getSex, Collectors.groupingBy(User::getAge)));
(5)分区
Stream<Integer> stream = Stream.of(4, 9, 1, 8, 5, 5, 7, 3, 6, 2);
Map<Boolean, List<Integer>> partMap = stream.collect(Collectors.partitioningBy(e -> e > 5));
//{false=[4, 1, 5, 5, 3, 2], true=[9, 8, 7, 6]}
说明:只能分为2个区。
声明:本文转自Stream 总结
Stream 总结的更多相关文章
- SQL Server-聚焦查询计划Stream Aggregate VS Hash Match Aggregate(二十)
前言 之前系列中在查询计划中一直出现Stream Aggregate,当时也只是做了基本了解,对于查询计划中出现的操作,我们都需要去详细研究下,只有这样才能对查询计划执行的每一步操作都了如指掌,所以才 ...
- Node.js:理解stream
Stream在node.js中是一个抽象的接口,基于EventEmitter,也是一种Buffer的高级封装,用来处理流数据.流模块便是提供各种API让我们可以很简单的使用Stream. 流分为四种类 ...
- node中的Stream-Readable和Writeable解读
在node中,只要涉及到文件IO的场景一般都会涉及到一个类-Stream.Stream是对IO设备的抽象表示,其在JAVA中也有涉及,主要体现在四个类-InputStream.Reader.Outpu ...
- nodejs中流(stream)的理解
nodejs的fs模块并没有提供一个copy的方法,但我们可以很容易的实现一个,比如: var source = fs.readFileSync('/path/to/source', {encodin ...
- Node学习笔记(一):stream流操作
NodeJs中谈及较多的可能就是Stream模块了,先写一个简单的ajax回调 $.post("index.php",{data:'aaa',order:'ccc'},functi ...
- Stream
Stream的好处 1.Stream AP的引入弥补了JAVA函数式编程的缺陷.2.Stream相比集合类占用内存更小:集合类里的元素是存储在内存里的,Stream里的元素是在访问的时候才被计算出来. ...
- Stream流
在Node中,存在各式各样不同的数据流,Stream(流)是一个由不同对象实现的抽象接口.例如请求HTTP服务器的request是一个 流,类似于stdout(标准输出):包括文件系统.HTTP 请求 ...
- [LeetCode] Data Stream as Disjoint Intervals 分离区间的数据流
Given a data stream input of non-negative integers a1, a2, ..., an, ..., summarize the numbers seen ...
- [LeetCode] Moving Average from Data Stream 从数据流中移动平均值
Given a stream of integers and a window size, calculate the moving average of all integers in the sl ...
- [LeetCode] Find Median from Data Stream 找出数据流的中位数
Median is the middle value in an ordered integer list. If the size of the list is even, there is no ...
随机推荐
- 1. 在Windows10上使用dbca配置oracle19.3.0.0时,报错DBT-50000 无法检查可用内存。
1.如图所示,在安装过程中,我遇到了错误提示,无法检查可用内存,导致安装失败. 在咨询后,认为是内存不足导致的问题,便清理了内存,重新安装.但是依旧出现以上内容,检查自己的内存大小,远远大于其安装所需 ...
- 【C++】枚举作为类函数返回值时需定义在使用之前
枚举定义在前,作为函数返回值在后 枚举定义在后,则函数返回值需用普通类型
- Ubuntu 安装 MinIO
MinIO是一个开源的高性能对象存储解决方案,支持多种安装方式,本例仅介绍最基础的单机安装方式. 下载安装文件 直接从MinIO官网下载安装文件. 下载服务端 wget https://dl.min. ...
- [转帖]故障分析 | 让top命令直接显示Java线程名?-- 解析OpenJDK的一个bug修复
https://zhuanlan.zhihu.com/p/413136873 作者:阎虎青DBLE 开源项目负责人,负责分布式数据库中间件研发工作:持续专注于数据库方面的技术,始终在一线从事开发:对数 ...
- Linux 处理CPU和内存参数的方式总结
Linux 处理CPU和内存参数的方式总结 关闭NUMA,关闭透明大页 比较简单的方法: vim /etc/default/grub 在 GRUB_CMDLINE_LINUX 里面添加配置: tran ...
- [转帖]kubelet 原理解析四:probeManager
https://segmentfault.com/a/1190000022163835 概述 在Kubernetes 中,系统和应用程序的健康检查任务是由 kubelet 来完成的,本文主要讨论kub ...
- 金蝶Cosmic虚拟机简单使用与总结
背景 知己知彼 简单学习下友商发出来的测试软件 看看有否对自己现在的工作有所指导 也看看对方的部署方式有啥优缺点 当然了仅是测试, 不是生产软件可能有失真. 注意 我没有测试序列号, 登录系统耗时很久 ...
- Grafana监控Redis的使用情况
Grafana监控Redis的使用情况 前言 最近在进行性能测试, 为了比较直观的将监控数据展示出来. 自己在周末时学习了下prometheus, 与之前的一个node_exporter一样, 本次进 ...
- echarts饼图的配置 封装组件的注意点
1==>tooltip 类似饰hover效果提示框组件.光标放上去会触发 2==>formatter // 饼图 {a}(系列名称),{b}(数据项名称),{c}(数值), {d}(百分比 ...
- 从零构建医疗领域知识图谱的KBQA问答系统:其中7类实体,约3.7万实体,21万实体关系。
从零构建医疗领域知识图谱的KBQA问答系统:其中7类实体,约3.7万实体,21万实体关系. 项目效果 以下两张图是系统实际运行效果: 1.项目运行方式 运行环境:Python3 数据库:neo4j 预 ...