一、Java8中的Stream
Java8之所以被广大的Java爱好者所喜爱,是因为它提供了一系列的关于集合的Stream操作。集合API是Java API中最重要的部分。基本上每一个java程序都离不开集合。尽管很重要,但是现有的集合处理在很多方面都无法满足需要。
一个原因是,许多其他的语言或者类库以声明的方式来处理特定的数据模型,比如SQL语言,你可以从表中查询,按条件过滤数据,并且以某种形式将数据分组,而不必需要了解查询是如何实现的——数据库帮你做所有的脏活。这样做的好处是你的代码很简洁。很遗憾,Java没有这种好东西,你需要用控制流程自己实现所有数据查询的底层的细节。
其次是你如何有效地处理包含大量数据的集合。理想情况下,为了加快处理过程,你会利用多核架构。但是并发程序不太好写,而且很容易出错。
Stream API很好的解决了这两个问题。它抽象出一种叫做流的东西让你以声明的方式处理数据,更重要的是,它还实现了多线程:帮你处理底层诸如线程、锁、条件变量、易变变量等等。
说了这么多,到底什么是流?通俗地讲,你可以认为是支持类似数据库操作的“花哨的迭代器”。技术上讲,它是从某个数据源获得的支持聚合操作的元素序列。
下面着重介绍一下正式的定义:
元素序列:针对特定元素类型的有序集合流提供了一个接口。但是流不会存储元素,只会根据要求对其做计算。
数据源:流所用到的数据源来自集合、数组或者I/O。
聚合操作:流支持类似数据库的操作以及函数式语言的基本操作,比如filter、map、reduce、findFirst、allMatch、sorted等待。
此外,流操作还有两种额外的基础属性根据不同的集合区分:
管道连接:许多流操作返回流本身,这种操作可以串联成很长的管道,这种方式更加有利于像延迟加载,短路,循环合并等操作。
内部迭代器:不像集合依赖外部迭代器,流操作在内部帮你实现了迭代器。
流接口在java.util.stream.Stream定义了许多操作,这些可以分为以下两类:像filter、sorted和map一样的可以被连接起来形成一个管道的操作。
像collect、findFirst和allMatch一样的终止管道并返回数据的操作。
可以被连接起来的操作被称为中间操作,它们能被连接起来是因为都返回流。中间操作都“很懒”并且可以被优化。终止一个流管道的操作被叫做结束操作,它们从流管道返回像List,Integer或者甚至是void等非流类型的数据。
下面我们介绍一下流里面的一些方法,完整的方法列表可以在java.util.stream.Stream找到。
Filter:有好几个方法可以用来从流里面过滤出元素:
filter:通过传递一个预期匹配的对象作为参数并返回一个包含所有匹配到的对象的流。
distinct:返回包含唯一元素的流(唯一性取决于元素相等的实现方式)。
limit:返回一个特定上限的流。
skip:返回一个丢弃前n个元素的流。
Matching:匹配是一个判断是否匹配到给定属性的普遍的数据处理模式。
Finding:提供了像findFirst和findAny等从流中取出任意的元素。它们能与像filter方法相连接。findFirst和findAny都返回一个可选对象。
Mapping:流支持映射方法,传递一个函数对象作为方法,把流中的元素转换成另一种类型。这种方法应用于单个元素,将其映射成新元素。
Reducing:把数据源中的所有元素结合起来提供单一的值。
Collectors:目前为止你所了解的方法都是返回另一个流或者一个像boolean,int类型的值,或者返回一个可选对象。相比之下,collect方法是一个结束操作,它可以使流里面的所有元素聚集到汇总结果。
传递给collect方法参数是一个java.util.stream.Collector类型的对象。Collector对象实际上定义了一个如何把流中的元素聚集到最终结果的方法。最开始,工厂方法Collectors.toList()被用来返回一个描述了如何把流转变成一个List的Collector对象。后来Collectors类又内建了很多相似的collectors变量。
二、实例
通过一个实例来对比下Java8之前的集合操作:
public class Demo { private int id; private String name; private double invoice; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getInvoice() { return invoice; } public void setInvoice(double invoice) { this.invoice = invoice; } }
public class StreamDemo { private static Logger logger = LoggerFactory.getLogger(StreamDemo.class); public static void main(String[] args){ List<Integer> idList1 = getIdsWithOldWay(convertData()); logger.info("以普通的Java实现方式:list={}",idList1); List<Integer> idList2 = getIdsWithStream(convertData()); logger.info("以Java8的实现方式:list={}",idList2); boolean flag = idList1.equals(idList2); logger.info("比较两种方式:compareResult={}",flag); } private static List<Integer> getIdsWithOldWay(List<Demo> demoList){ List<Integer> idList = Lists.newArrayList(); List<Demo> demos = Lists.newArrayList(); for(Demo demo : demoList){ if("张三丰".equals(demo.getName())){ if(demo.getInvoice() > 0.00){ demos.add(demo); } } } Collections.sort(demos, new Comparator<Demo>() { @Override public int compare(Demo demo1, Demo demo2) { return Double.compare(demo1.getInvoice(),demo2.getInvoice()); } }); for(Demo demo : demos){ idList.add(demo.getId()); } return idList.subList(0,3); } private static List<Integer> getIdsWithStream(List<Demo> demoList){ return demoList.stream() .filter(demo -> "张三丰".equals(demo.getName())) .filter(demo -> demo.getInvoice() > 0.00) .sorted(Comparator.comparingDouble(Demo :: getInvoice)) .map(Demo :: getId) .limit(3) .collect(Collectors.toList()); } private static List<Demo> convertData(){ List<Demo> demoList = Lists.newArrayList(); Demo demo1 = new Demo(); demo1.setId(1); demo1.setName("张三丰"); demo1.setInvoice(0.03); demoList.add(demo1); Demo demo2 = new Demo(); demo2.setId(2); demo2.setName("张三丰"); demo2.setInvoice(0.02); demoList.add(demo2); Demo demo3 = new Demo(); demo3.setId(3); demo3.setName("张三丰"); demo3.setInvoice(0.01); demoList.add(demo3); Demo demo4 = new Demo(); demo4.setId(4); demo4.setName("张三丰"); demo4.setInvoice(0.06); demoList.add(demo4); Demo demo5 = new Demo(); demo5.setId(5); demo5.setName("张三丰"); demo5.setInvoice(0.05); demoList.add(demo5); Demo demo6 = new Demo(); demo6.setId(6); demo6.setName("张三丰"); demo6.setInvoice(0.04); demoList.add(demo6); return demoList; } }
三、运行结果
14:27:26.518 [main] INFO c.pajk.docplatformmanager.StreamDemo - 以普通的Java实现方式:list=[3, 2, 1]
14:27:26.618 [main] INFO c.pajk.docplatformmanager.StreamDemo - 以Java8的实现方式:list=[3, 2, 1]
14:27:26.618 [main] INFO c.pajk.docplatformmanager.StreamDemo - 比较两种方式:compareResult=true
相关推荐
Java多线程实现数据切割批量执行,实现限流操作。 java线程池Executors实现数据批量操作。 批量异步Executors处理数据,实现限流操作,QPS限流。 线程池调用第三方接口限流实现逻辑。 案例适合: 1.批量处理大数据。...
Flume 是一个分布式、可靠和高可用的服务,用于收集、聚合以及移动大量日志数据,使用一个简单灵活的架构,就流数据模型。这是一个可靠、容错的服务。 彩信发送开发包 apimms apimms 提供了各种语言用来发送彩信...
Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...
对Java IO流操作感兴趣的开发人员 需要进行文件读写、网络传输等IO操作的程序员 使用场景 该代码资源可以用于教学、自学以及实际项目开发中的参考。 教学:作为教学示例演示给学生 自学:通过查看示例代码来学习和...
java8流源码java8-commons 标准的 Java8 库无法提供足够的方法来操作其核心类。 java8-commons 提供了额外的类和方法。 该项目仍在开发中,API 可能会发生变化。 目标 充分利用 Java8 的特性 简单易用 类型安全 轻的...
JsonFlow工作流基于自研的流程设计器 + 自研后端Java工作流引擎,组成了一套纯JSON数据交互的自研工作流引擎系统 + 工作流管理系统。本系统无论前端还是后端,其学习成本明显低于开源工作流引擎及附带流程设计器,...
Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...
Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...
Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...
Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...
Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...
javaOOP必看精华视频资料,1:主要介绍IO流中的递归 2:文件输出导出数据与文件输入导入数据的构造方法 3:递归求阶乘代码实现及内存讲解 4:不死神兔问题案例 5:IO流基类概述及一个简单的需求分析 6:...
本系统是简单模仿银行的一般的存取款操作 相对简单 对于刚进入JAVA世界不久的人有一定的帮助 文件流 图形化界面等对深入的理解JAVA还需要对此文件做一些必要的修改
2.4 提取子流和组合流 26 2.5 有状态的转换 27 2.6 简单的聚合方法 28 2.7 Optional类型 29 2.7.1 使用Optional值 29 2.7.2 创建可选值 30 2.7.3 使用flatMap来组合可选值函数 31 2.8 聚合操作 32 2.9 收集结果 33 ...
Outer_8.java 外部类示例8 overrideMember_1.java 成员方法覆盖示例1 overrideMember_2.java 成员方法覆盖示例2 overrideMember_3.java 成员方法覆盖示例3 overrideMember_4.java 成员方法覆盖示例4 ...
vue手写一个自定义操作的工作流:适用简单的、想要手写的、不借用三方插件的工作流开发。样式自定义,可随意扩展、随意添加条件、自定义条件
7 Java流 用输入输出流实现从一个文本文件中读写简单数据。 8 泛型与容器 编程实现set、list与map的简单应用。 9 图形用户界面 用图形界面工具,结合事件处理机制,实现一个可视化的计算器。 10 JDBC基础 使用JDBC...
项目概述: 本项目是基于Java语言...- 简化Flink SQL:使Flink SQL的使用变得简单直观,易于操作和调试。 本框架不仅提高了开发效率,还让Flink流处理和批处理变得更加灵活和高效,是数据工程师和开发者的强大工具。
一个简单的JAVA IO程序,希望对新手有帮助