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 ...
随机推荐
- [转帖]使用 mydumper/loader 全量导入数据
数据迁移 mydumper 是一个更强大的数据迁移工具,具体可以参考 https://github.com/maxbube/mydumper. 我们使用 mydumper 从 MySQL 导出数据,然 ...
- [转帖]CTF -bugku-misc(持续更新直到全部刷完)
CTF -bugku-misc(持续更新直到全部刷完) https://www.cnblogs.com/cat47/p/11432475.html 1.签到题 点开可见.(这题就不浪费键盘了) CTF ...
- [转帖]Jmeter学习笔记(十九)——后置处理器之正则表达式的使用
https://www.cnblogs.com/pachongshangdexuebi/p/11733005.html 一.正则表达式提取器的作用 允许用户从服务器的响应中通过使用perl的正则表达式 ...
- [转帖]jmeter正则表达式应用-01篇
如图所示 1.先新建一个login的http请求,然后再login的请求下新增一个正则表达式提取器,增加一个查看结果树查看结果 假如后端接口返回的数据为"{'msg': 'login suc ...
- Jmeter学习之四_kingbaseV8R6数据库的简单验证
Jmeter学习之四_kingbaseV8R6数据库的简单验证 背景 周一没去报道, 因为我忘记体检了... 继续在家进行学习提高自己. jmeter周末时开始看的. 今天想着继续研究一下对数据库的处 ...
- Nginx的Keepalive的简单学习
摘要 最近发现某项目的Nginx负载服务器上面有很多Time_wait的TCP连接 可以使用命令 netstat -n |awk '/^tcp/ {++S[$NF]} END{for (a in S) ...
- 简单的获取ESXi服务器上面开启了多少个vCPU的办法
开启ssh 执行命令 esxcli vm process list |grep Config |cut -b 17- |xargs cat |grep numvcpus |cut -d " ...
- redis 6源码解析之 object
redis对象作为redis存储的基本单元,对应redisDb->dict 中的dictEntry->key和dictEntry->val. 更全面的图谱 源码解析参见:object ...
- echarts饼图中央自定义文字
var option = { tooltip: { trigger: 'item' }, legend: { top: '5%', left: 'center' }, //中央自定义文字 title: ...
- 【七】强化学习之Policy Gradient---PaddlePaddlle【PARL】框架{飞桨}
相关文章: [一]飞桨paddle[GPU.CPU]安装以及环境配置+python入门教学 [二]-Parl基础命令 [三]-Notebook.&pdb.ipdb 调试 [四]-强化学习入门简 ...