java8新特性五-Stream
继上次学习过Java8中的非常重要的Lambda表达式之后,接下来就要学习另一个也比较重要的知识啦,也就如标题所示:Stream,而它的学习是完全依赖于之前学习的Lambda表达式。
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
+--------------------+ +------+ +------+ +---+ +-------+
| stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
+--------------------+ +------+ +------+ +---+ +-------+
以上的流程转换为 Java 代码为:
class Apple{
private int weigth;
private String color;
public int getWeigth() {
return weigth;
}
public void setWeigth(int weigth) {
this.weigth = weigth;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Apple(int weigth, String color) {
this.weigth = weigth;
this.color = color;
}
} @Test
public void testStream(){
List<Apple> transactionsIds = new ArrayList<>();
transactionsIds.add(new Apple(1,"红色"));
transactionsIds.add(new Apple(2,"绿色"));
transactionsIds.add(new Apple(3,"绿色"));
transactionsIds.add(new Apple(2,"绿色")); int weight= transactionsIds.stream()
.filter(app ->app.getColor().equals("绿色"))
.sorted(( app1, app2)->app2.getWeigth()-app1.getWeigth())
.mapToInt(Apple::getWeigth)
.sum();
System.out.println(weight);
}
以上代码的写法可读性比较高,几乎一眼能看出做了哪些操作。
简介
Stream(流)是一个来自数据源的元素队列并支持聚合操作
- 元素队列元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
- 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
- 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
和以前的Collection操作不同, Stream操作还有两个基础的特征:
- Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
- 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。
实例
生成流
在 Java 8 中, 集合接口有两个方法来生成流:
stream() − 为集合创建串行流。
parallelStream() − 为集合创建并行流。
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
forEach
Stream 提供了新的方法 'forEach' 来迭代流中的每个数据。以下代码片段使用 forEach 输出了10个随机数:
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
map
map 方法用于映射每个元素到对应的结果,以下代码片段使用 map 输出了元素对应的平方数:
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 获取对应的平方数
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
filter
filter 方法用于通过设置的条件过滤出元素。以下代码片段使用 filter 方法过滤出空字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
int count = strings.stream().filter(string -> string.isEmpty()).count();
limit
limit 方法用于获取指定数量的流。 以下代码片段使用 limit 方法打印出 10 条数据:
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
sorted
sorted 方法用于对流进行排序。以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:
Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);
并行(parallel)程序
parallelStream 是流并行处理程序的代替方法。以下实例我们使用 parallelStream 来输出空字符串的数量:
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
int count = strings.parallelStream().filter(string -> string.isEmpty()).count();
我们可以很容易的在顺序运行和并行直接切换。
Collectors
Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
System.out.println("筛选列表: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合并字符串: " + mergedString);
统计
另外,一些产生统计结果的收集器也非常有用。它们主要用于int、double、long等基本类型上,它们可以用来产生类似如下的统计结果。
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("列表中最大的数 : " + stats.getMax());
System.out.println("列表中最小的数 : " + stats.getMin());
System.out.println("所有数之和 : " + stats.getSum());
System.out.println("平均数 : " + stats.getAverage());
分析
一、stream支持并行,这个怎么验证呢?可以通过下面两张图可知
二、stream到底如何工作的?
下图很清晰的展示了stream的工作方式,并且是一次性的,即操作过的stream无法再次被操作。
三、stream有啥好处?
下图可以说明stream的优势,很明显,就是速度要快,因为stream只操作符合条件的数据,有短路的特点。
四、stream的迭代方式变化,也就是上文提及的由以前的“外部迭代”改成了“内部迭代”
五、stream的方法分为两种,一种是Intermediate Operations(中间操作),一种是terminal operations(终止操作),这个应该好理解,继续操作的命令就是中间操作。这里为什么要区分这两种操作的,因为stream操作是属于延迟操作,也就是说这段链式代码必须遇到terminal operations才会去执行,否则是不会有任何效果,这个是容易踩得坑。
这里大致列一下,其实每个方法上大神都有说明是什么操作,另外我们根据返回类型也能确定是属于什么操作。
六、stream的中间操作是不停的for循环吗?
对于一个流可能有若干个中间操作,对于这些操作并非降低了整体的执行性能,反而会有提升,比如说增加了三个中间操作,可能感受会有三次循环,但是实际上最终只会循环一次,可以这么简单的理解,以于这些中间操作的行为都是存放于Stream中的一个容器当中,一旦遇到终止操作时,则会将这些行为按照咱们写的顺序逐个的应用到集合当中的每一个元素上,所以说性能上不会有任何影响。
七、stream会修改源数据吗?
并不会修改底层的数据源,集合可以作为流的底层数据源
参考https://www.cnblogs.com/webor2006/p/7887244.html,https://www.runoob.com/java/java8-streams.html
java8新特性五-Stream的更多相关文章
- 乐字节-Java8新特性之Stream流(上)
上一篇文章,小乐给大家介绍了<Java8新特性之方法引用>,下面接下来小乐将会给大家介绍Java8新特性之Stream,称之为流,本篇文章为上半部分. 1.什么是流? Java Se中对于 ...
- Java8 新特性之Stream API
1. Stream 概述 Stream 是Java8中处理集合的关键抽象概念,可以对集合执行非常复杂的查找,过滤和映射数据等操作; 使用 Stream API 对集合数据进行操作,就类似于使用 SQL ...
- 【Java8新特性】Stream API有哪些中间操作?看完你也可以吊打面试官!!
写在前面 在上一篇<[Java8新特性]面试官问我:Java8中创建Stream流有哪几种方式?>中,一名读者去面试被面试官暴虐!归根结底,那哥儿们还是对Java8的新特性不是很了解呀!那 ...
- 【Java8新特性】- Stream流
Java8新特性 - Stream流的应用 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! ...
- Java8 新特性 Lambda & Stream API
目录 Lambda & Stream API 1 Lambda表达式 1.1 为什么要使用lambda表达式 1.2 Lambda表达式语法 1.3 函数式接口 1.3.1 什么是函数式接口? ...
- Java8新特性之Stream
原文链接:http://ifeve.com/stream/ Java8初体验(二)Stream语法详解 感谢同事[天锦]的投稿.投稿请联系 tengfei@ifeve.com上篇文章Java8初体验( ...
- Java8新特性--流(Stream)
1.简介 Java 8是Java自Java 5(发布于2004年)之后的最重要的版本.这个版本包含语言.编译器.库.工具和JVM等方面的十多个新特性.在本文中我们一起来学习引入的一个新特性- ...
- java8 新特性入门 stream/lambda
Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利.高效的聚合操作(aggregate operation),或者大批量数据操作 (b ...
- 【Java8新特性】Stream(分类+案例)
一.Stream概述 什么是Stream? Stream是Java8引入的全新概念,它用来处理集合中的数据,可以让你以一种声明的方式处理数据. Stream 使用一种类似用 SQL 语句从数据库查询数 ...
随机推荐
- Windows10安装Redis过程
下载 Redis下载地址:https://github.com/microsoftarchive/redis/releases 以3.2.100版本为例,下载Redis-x64-3.2.100.zip ...
- oracle 按每天,每周,每月,每季度,每年查询统计数据
oracle 按每天,每周,每月,每季度,每年查询统计数据 //按天统计 select count(dataid) as 每天操作数量, sum() from tablename group by t ...
- (浙江金华)Day 1 组合数计数
目录 Day 1 组合计数 1.组合数 (1).C(n,m) 读作n选m,二项式系数 : (2).n个东西里选m个的方案数 不关心选的顺序: (3).二项式系数--->多项式系数: 2.组合数计 ...
- 洛谷 P2212 [USACO14MAR]浇地Watering the Fields 题解
P2212 [USACO14MAR]浇地Watering the Fields 题目描述 Due to a lack of rain, Farmer John wants to build an ir ...
- 洛谷 P5506 封锁
目录 题目 思路 \(Code\) 题目 P5506 封锁 思路 模拟 \(\large\text{读题一定要细心}\) 解释都在代码里. \(Code\) #include<bits/stdc ...
- GoCN每日新闻(2019-09-30)
GoCN每日新闻(2019-09-30) 1. 使用Sqlmock测试数据库 https://medium.com/ralali-engineering/testing-database-using- ...
- java.lang.Thread类的静态方法sleep()和yield()的比较
[线程让步yield()方法] yield()方法可以让当前正在执行的线程暂停,但它不会阻塞该线程,它只是将该线程从运行状态转入就绪状态. 只是让当前的线程暂停一下,让系统的线程调度器重新调度一次. ...
- [C++] explicit关键字使用方法
C++中,构造函数可以用作自动类型转换,但是这种转换不一定是程序所需要的,有时会导致错误的类型转换. 下面的代码,在mian函数中,将一个整形赋值为对象类型. #include "iostr ...
- log4net 控制台和文件和数据库输出三种方式
1.新建console应用项目SendEvaluateDataToProvinceConsole 2.选择SendEvaluateDataToProvinceConsole项目右键 选择 管理NuGe ...
- 解决iis内存占用过大的问题--ZT
解决iis内存占用过大的问题 在IIS6下,经常出现w3wp的内存占用不能及时释放,从而导致服务器响应速度很慢. 今天研究了一下,可以做以下配置: 1.在IIS中对每个网站进行单独的应用程序池配置.即 ...