java8新特性stream深入解析

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

继续java8源码的发烧热,越看越是有充实的感觉。

数据时代下的产物

Java顺应时代的发展推出的高效处理大量数据能力的api,它专注于对集合对象进行各种非常便利、高效的聚合操作,借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,可以很方便地写出高性能的并发程序。

Stream可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

核心概念理解

一个流的操作 = 创建流 + 中间操作 + 结果转换。

  1. 创建流:指从集合转换过滤,数值转换过滤、I/O转换、创建等等;
  2. 中间操作:指对流中的数据进行聚合,如filter\map\sorted\reduce、distinct等等;
  3. 结果转换:指将流进行输出,打印、转换成array、转换成collection等;

Stream重要点:

  1. 流是不存储值的,只是一个管道过程
  2. 单个流只能被使用一次,再次被使用报错
  3. 流是支持函数式调用

测试样例定义

static List<ICar> cars = new ArrayList<>();static Map<Integer,String> kv = new HashMap<>();public static void init(){for(int i = 1; i <= 10; i++){WeiLaiCar car = new WeiLaiCar();car.setCarWheel(i);cars.add(car);kv.put(i,i+"-value");}
}

源码深度

java.util.stream

在java.util.stream目录下可以看出有多种stream可以使用。Stream是支持泛型的对象的流,另外还提供了double\int\long常用数据类型的流,但他们提供的方法基本类似。

1、流是管道内部单向不可逆操作

Random random = new Random();
IntStream intStream = random.ints(10);
intStream.limit(6).forEach(PrintUtil::printTest);
intStream.toArray();

这里的第二个intStream.toArray()执行会报错误:IllegalStateException: stream has already been operated upon or closed,流创建流到结束流单个管道内只能顺序一次使用,想要再次使用就得从源头重新创建流重新开始;

Random random = new Random();
IntStream intStream = random.ints(10);
intStream.limit(6).forEach(PrintUtil::printTest);
random.ints(15).toArray();

2、Stream的串行和并行

流的计算提供了两种模式:串行流和并行流,认是创建串行流。

  • 提供流方法parallel()和sequential()在串并流间相互转换。
  • 在Collection接口上添加了两个方法stream()\parallelStream(),parallel是并行计算的。这两个方法的内部实现皆是通过StreamSupport.stream(xx,aa)来实现,该方法的aa参数是boolean代表是否开启并行流;

3、collection与stream转换

流提供有方法toArray()转换成数组,也提供了方法collect()转换为list\set\Collection集合;同时Arrays.stream()方法可以把数组转换为流。

//list -> stream
Stream<ICar> carStream = cars.parallelStream();
carStream.filter(a -> a.getWheelCount() > 5).map(a-> a.hashCode()+"|"+a.getWheelCount()).forEach(PrintUtil::printTest);
//list转换为并发stream并打印符合条件的对象的hashcode和wheel数量:730140433|8//stream -> list
Stream<ICar> tmp = cars.stream();
List<ICar> carList = tmp.collect(Collectors.toList());
carList.forEach(PrintUtil::printTest);
//通过collect方法把stream转换为list并打印对象全称:com.ts.util.optional.WeiLaiCar@4e515669//array -> stream
ICar[] carss = {new WeiLaiCar(1),new WeiLaiCar(2)};
Arrays.stream(carss).filter(a -> a.getWheelCount() >2).forEach(PrintUtil::printTest);
//最终输出8个wheel大于2个的对象,并打印对象全称:com.ts.util.optional.WeiLaiCar@4dcbadb4//stream -> array
Object[] tmps = cars.stream().filter(a ->a.getWheelCount()>7).toArray();
PrintUtil.printTest(tmps.length);
//从cars中转换stream选出wheel大于7个的,转换为数值最终输出数量为:3

4、stream的排序

默认的排序要求排序对象是自然的有些值,一般dubble\int\long等;其他的类型需要主动定义comparator接口比较逻辑。

//默认sorted()要求是值natural order,即是自然顺序的
cars.stream().map(a->a.getWheelCount()).sorted().forEach(PrintUtil::printTest);
//先将对象的int类型的wheel聚合成集合,再使用默认排序(顺序)进行打印:1 2 3 4 5 6 ...10//自定义comparator,也可以在对象之间实现Comparator接口
cars.stream().sorted(Comparator.comparingInt(ICar::getWheelCount)).map(a->a.getWheelCount()).forEach(PrintUtil::printTest);
//自定义使用ICar的int类型wheel字段顺序比较,之后再将对象的wheel字段聚合进行打印:1 2 3 4 5 6 ...10
cars.stream().sorted(Comparator.comparingInt(ICar::getWheelCount).reversed()).map(a->a.getWheelCount()).forEach(PrintUtil::printTest);
//自定义使用ICar的int类型wheel字段顺序比较后再逆转,之后再将对象的wheel字段聚合进行打印
//与上面的顺序正好相反:10 9 8 7 ... 1

流包下重要的工具类

  1. Collectors 提供了很多 reduction 操作,都是静态的方法,如聚合成集合或者其他类型,官网例子如下:
// Accumulate names into a List
List<String> list = people.stream().map(Person::getName).collect(Collectors.toList());// Accumulate names into a TreeSet
Set<String> set = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new));// Convert elements to strings and concatenate them, separated by commas
String joined = things.stream().map(Object::toString).collect(Collectors.joining(", "));// Compute sum of salaries of employee
int total = employees.stream().collect(Collectors.summingInt(Employee::getSalary)));// Group employees by department
Map<Department, List<Employee>> byDept = employees.stream().collect(Collectors.groupingBy(Employee::getDepartment));// Compute sum of salaries by department
Map<Department, Integer> totalByDept = employees.stream().collect(Collectors.groupingBy(Employee::getDepartment,Collectors.summingInt(Employee::getSalary)));// Partition students into passing and failing
Map<Boolean, List<Student>> passingFailing = students.stream().collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
  1. StreamSupport 是stream的底层创建操作方法实现类,让我们查看一下Stream类的部分方法源码:
    /*** Returns an empty sequential {@code Stream}.** @param <T> the type of stream elements* @return an empty sequential stream*/public static<T> Stream<T> empty() {return StreamSupport.stream(Spliterators.<T>emptySpliterator(), false);}/*** Returns a sequential {@code Stream} containing a single element.** @param t the single element* @param <T> the type of stream elements* @return a singleton sequential stream*/public static<T> Stream<T> of(T t) {return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);}
  1. 其他创建stream的方式,通过Stream的静态方法或者StreamSupport类:
Stream<String> stringStream = Stream.of("1","a","c");
stringStream.forEach(PrintUtil::printTest);
// 1 a cStream<Integer> integerStream = Stream.empty();
PrintUtil.printTest("count is " + integerStream.count());
//count is 0double[] tm = {22D,1.11D,33D,20.12D,11.02D,9.34D};
DoubleStream doubleStream = StreamSupport.doubleStream(Spliterators.spliterator(tm,0,5,1),true);
doubleStream.filter(a -> a < 20).forEach(PrintUtil::printTest);
//1.11 11.02

要主动拥抱新技术的出现

看着公司年轻的工程师一个比一个年轻,我变的更加努力了。要鞭策自己在项目中多尝试使用新API各种类和方法以锻炼自己,这些东西就是需要多用你才能发现区别并提升你的技术能力。

就算是写业务的也能写出不一样的水平。时常告诉自己去学习,追求进步不要做茫茫的小白。 对于一个工程师来说学习能力是你在这个行业必备的能力。

测试用例地址:play-java-sample


作者:Owen Jia

欢迎关注他的博客:Owen Blog

坚持写博客成了我的一种寄托

转载于:https://my.oschina.net/timestorm/blog/3009416

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/275902.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql内连接的自连接_mysql 内连接、外连接、自连接

一)内连接(等值连接)&#xff1a;查询客户姓名&#xff0c;订单编号&#xff0c;订单价格---------------------------------------------------select c.name,o.isbn,o.pricefrom customers c inner join orders owhere c.id o.customers_id;-------------------------------…

关于ASP.NET MVC

我是否要学习一下ASP.NET MVC呢&#xff1f;因爲从它刚发布的时候就已经初步的学习了一下&#xff0c;可是一直没有坚持下来。不过心里对于这份惦记&#xff0c;又让我始终放不下&#xff0c;看来应该抽个时间来系统的学习一下。 就这样吧&#xff0c;把自己的博客当成微博来使…

版式设计与创意 pdf_恋爱与版式

版式设计与创意 pdfSince its beginnings, Libération has been characterized by a very distinctive use of typeface, to such an extent that Libé has put its mark on fonts from across different eras, appropriating these in a certain way.小号因斯它的起点&…

移动网站开发——标记语言

移动互联网被称为“第五次科技革命”&#xff0c;而随着iPhone和Android等智能手机的日渐流行和iPad等平板电脑的出现&#xff0c;移动互联网的潜力和趋势也愈发显现&#xff0c;针对移动设备的网站开发越来越受到关注&#xff0c;国内很多公司也开始重视面向所有移动设备的网站…

mysql适配器_MySQL适配器PyMySQL详解

import pymysqlimport datainfoimport time#获取参数host datainfo.hostusername datainfo.usernamepassword datainfo.passworddatabase datainfo.dbprint()#测试数据库连接def testconnect():#打开数据库链接db pymysql.connect(host,username,password,database)#使用c…

获取当前Tomcat实例的端口

有时需要在当前代码中获取当前Server实例的端口号, 通过HttpServletRequest请求可以, 但有时也需要在没有请求的情况下获取到端口号. 用以下方法是可以获取到的: public int getHttpPort() {try {MBeanServer server;if (MBeanServerFactory.findMBeanServer(null).size() >…

前端技术未来三年前瞻性思考

大家好&#xff0c;我是若川。今天推荐云谦大佬的一篇好文章&#xff0c;值得收藏。点击下方卡片关注我、加个星标&#xff0c;或者查看源码等系列文章。学习源码整体架构系列、年度总结、JS基础系列习惯从业务场景、用户体验、研发速度、维护成本四个维度来看框架等前端技术&a…

微信临时素材接口_在接口中表达临时性

微信临时素材接口When interacting with today’s graphic user interfaces (GUI), we experience a sense of realism. As of now, certain aspects of realism (for example animations) create the appearance that user interface graphics behave in accordance with the …

程序员,当你写程序写累了怎么办。

记得泡泡网的CEO李想说过这样一句话&#xff0c;大体就是&#xff1a;做一件事情&#xff0c;一开始是兴趣使然&#xff0c;然而当三分钟热度过去之后&#xff0c;就要靠毅力支撑自己来完成它。至少我到现在是能非常深刻的体会这句话。一开始再怎么喜欢做一件事&#xff0c;要想…

mysql 导致iis 假死_解决IIS无响应假死状态

1 查看服务器iis的w3wp.exe对应的应用程序池在IIS6下&#xff0c;经常出现w3wp的内存占用不能及时释放&#xff0c;从而导致服务器响应速度很慢。今天研究了一下&#xff0c;可以做以下配置&#xff1a;1、在IIS中对每个网站进行单独的应用程序池配置。即互相之间不影响。2、设…

Swift 5将强制执行内存独占访问

Swift 5将带来改进的Swift程序内存安全性&#xff0c;在程序的其他部分修改变量时&#xff0c;不允许通过其他变量名来访问这些变量。这个变更对现有应用程序的行为和Swift编译器本身都有重要影响。Swift 5将带来改进的Swift程序内存安全性&#xff0c;在程序的其他部分修改变量…

GitHub 支持上传视频文件啦!

大家好&#xff0c;我是若川。今天周六&#xff0c;分享一篇热点新闻。文章较短&#xff0c;预计5分钟可看完。近日 Github 宣布支持了视频上传功能&#xff0c;意味着&#xff0c;大家在提 issue 时可以携带视频了&#xff0c;这极大地提高了开发者和维护者的效率&#xff0c;…

ui设计 网络错误_UI设计人员常犯的10个错误

ui设计 网络错误重点 (Top highlight)1.不考虑范围 (1. Disregarding scope)It’s not uncommon for designers to introduce features that will overcomplicate the development process while bringing no additional value to the application. Focusing on the business o…

灰色的生命

也许幸福从来没有在我身边也许是已经在我身边但我抓不住,摸不着 你的出现让我惊奇为我灰色的生命添上了从没见过的色彩我不相信这一切都是我的 不相信总是害怕相信了之后却要面对残酷的现实 但为何你让我相信所有抓住了希望却又转过身没有离去但让一切停止望着你不想说…

小程序 node.js mysql_基于Node.js+MySQL开发的开源微信小程序B2C商城(页面高仿网易严选)...

高仿网易严选的微信小程序商城(微信小程序客户端)界面高仿网易严选商城(主要是2016年wap版)测试数据采集自网易严选商城功能和数据库参考ecshop服务端api基于&#xff2e;ode.jsThinkJSMySQL计划添加基于Vue.js的后台管理系统、PC版、&#xff37;ap版项目截图功能列表首页分类…

前端菜鸟笔记 Day-5 CSS 高级

文章大纲来源&#xff1a;【Day 5】CSS 高级 CSS 选择器CSS 拓展CSS 单位CSS 参考手册CSS 选择器 内容引用&#xff1a;CSS 选择器 元素选择器 html { ... } 复制代码选择器分组 h2, p { ... } 复制代码类选择器 .important { ... } p.warning { ... } .important.warning { .…

推荐几个干货超多助你成长的前端大佬

不得不说&#xff0c;如今比前些年学习资料多很多了。现在的前端公众号也挺多的&#xff0c;这里推荐几个前端大佬运营的公众号&#xff0c;都是聚焦前端垂直领域的优质公众号&#xff0c;关注这些公众号至少可以&#xff1a;1、了解现在前端技术发展情况和未来发展趋势&#x…

背景图片_背景

背景图片A designer’s journey is one that’s littered with many portfolios. Many of which have been reduced to a mere 404 error page, an abandoned link or another archive in the folders. Recently, while updating my portfolio, all the forgotten versions tha…

解决《Mobile绘制背景图片》中的问题

与PC平台的开发相比&#xff0c;Mobile的开发麻烦了许多&#xff0c;至少这是我的感觉 。 谢谢&#xff0d;&#xff0d;“ Fly Pig(^^)” 的文章《Mobile开发(绘制背景图片) 》 http://www.cnblogs.com/Bright-Liang/archive/2009/06/11/1501309.html 不过对于我这种低手来说&…

mysql 5.6.31 winx64_详解介绍MySQL5.6.31winx64.zip安装配置的图文教程

这篇文章主要介绍了MySQL5.6.31 winx64.zip 安装配置教程详解,非常不错&#xff0c;具有参考借鉴价值&#xff0c;需要的朋友可以参考下#1. 下载##2.解压到本地 修改必要配置my*.ini#3.mysql installadmin模式启动cmdcd mysql目录/bin执行安装&#xff1a; mysqld -install启动…