成为Java流大师–第3部分:终端操作

比尔·盖茨曾经说过:“我选择一个懒惰的人去做一件困难的事情,因为一个懒惰的人会找到一个简单的方法来做。” 关于流,没有什么比这更真实了。 在本文中,您将学习Stream如何通过在调用终端操作之前不对源元素执行任何计算来避免不必要的工作,以及源如何只生成最少数量的元素。

本文是五分之三,以GitHub存储库为补充,其中包含每个单元的说明和练习。
第1部分:创建流
第2部分:中级操作 第三部分:终端操作 第4部分:数据库流 第5部分:使用流创建数据库应用程序

终端机操作

现在我们熟悉Stream管道的初始化和构造,我们需要一种处理输出的方法。 终端操作通过从其余元素(例如
count() )或副作用(例如
forEach(Consumer) )。

在启动终端操作之前,Stream将不会对源的元素执行任何计算。 这意味着仅在需要时才使用源元素,这是避免不必要工作的明智方法。 这也意味着一旦应用了终端操作,流将被消耗,并且无法再添加其他操作。

让我们看一下可以应用于Stream管道末尾的哪些终端操作:

ForEach和ForEachOrdered

流的可能用例可能是更新某些或所有元素的属性,或者为什么不只是出于调试目的而将它们打印出来。 无论哪种方式,我们都不希望收集或计数输出,而是通过产生副作用而不返回值来进行。

这是目的
forEach()
forEachOrdered() 。 他们俩都 Consumer并终止Stream,而不返回任何内容。 这些操作之间的区别仅仅是 forEachOrdered()承诺按照元素在Stream中出现的顺序调用提供的Consumer。 forEach()仅承诺以任何顺序调用Consumer。 后一种变体对并行流很有用。

在下面的简单情况下,我们在一行中打印出Stream的每个元素。

 Stream.of( "Monkey" , "Lion" , "Giraffe" , "Lemur" , “Lion”  ) .forEachOrdered(System.out::print); 

这将产生以下输出:

 MonkeyLionGiraffeLemurLion 
 <br> 

收集元素

Streams的常见用法是构建元素的“存储桶”,或更具体地说,构建包含特定元素集合的数据结构。 这可以通过调用终端操作来完成
Stream末尾的collect() ,因此要求它将元素收集到给定的数据结构中。 我们可以提供称为
Collector collect()操作,可以根据手头的问题使用许多不同的预定义类型。 以下是一些非常有用的选项:

收集到设置

我们可以将所有元素收集到
通过使用收集器收集Stream的元素来简单地进行Set
toSet()

 Set<String> collectToSet = Stream.of( "Monkey" , "Lion" , "Giraffe" , "Lemur" , "Lion"  ) .collect(Collectors.toSet()); 
 toSet: [Monkey, Lion, Giraffe, Lemur] 

收集到清单

同样,可以将元素收集到
List使用
toList()收集器。

 List<String> collectToList = Stream.of( "Monkey" , "Lion" , "Giraffe" , "Lemur" , "Lion"  ) .collect(Collectors.toList()); 
 collectToList: [Monkey, Lion, Giraffe, Lemur, Lion] 

收集到一般收藏

在更一般的情况下,可以将Stream的元素收集到任何
通过仅提供所需构造函数的Collection
Collection类型。 构造函数的例子是 LinkedList::newLinkedHashSet::newPriorityQueue::new

 LinkedList<String> collectToCollection = Stream.of( "Monkey" , "Lion" , "Giraffe" , "Lemur" , "Lion"  ) .collect(Collectors.toCollection(LinkedList:: new )); 
 collectToCollection: [Monkey, Lion, Giraffe, Lemur, Lion] 

收集到阵列

由于数组是固定大小的容器,而不是灵活的容器 Collection ,有充分的理由进行特殊的终端操作, toArray() ,以将元素创建并存储在Array中。 请注意,仅调用toArray()会导致Objects Array ,因为该方法无法自行创建类型化数组。 下面我们展示如何使用String数组的构造函数来提供类型化的数组String[]

 String[] toArray = Stream.of( "Monkey" , "Lion" , "Giraffe" , "Lemur" , "Lion"  ) .toArray(String[]:: new ); 
 toArray: [Monkey, Lion, Giraffe, Lemur, Lion] 

收集到地图

我们可能想从元素中提取信息,并将结果提供为Map 。 为此,我们使用收集器toMap() ,它需要两个
Functions按键对应的映射器和值映射器。

该示例显示了不同的动物如何与它们名称中不同字符的数量相关联。 我们使用中间操作distinct()来确保仅在Map添加唯一键(如果键不是唯一的,则必须提供toMap()收集器的变体,其中必须提供用于合并的解析器来自相等键的结果)。

 Map<String, Integer> toMap = Stream.of( "Monkey" , "Lion" , "Giraffe" , "Lemur" , "Lion"  ) .distinct() .collect(Collectors.toMap( Function.identity(), //Function<String, K> keyMapper s -> ( int ) s.chars().distinct().count() // Function<String, V> valueMapper )); 
 toMap: {Monkey= 6 , Lion= 4 , Lemur= 5 , Giraffe= 6 }  (*) 

(*)请注意,键顺序是未定义的。

收集分组

坚持使用桶的类比,我们实际上可以同时处理多个桶。 有一个非常有用的Collector名为
groupingBy()根据某些属性将元素划分为不同的组,从而通过称为“分类器”的某种内容提取该属性。 这样的操作的输出是Map 。 下面我们演示如何根据动物的名字的首字母对动物进行分组。

 Map<Character, List<String>> groupingByList = Stream.of( "Monkey" , "Lion" , "Giraffe" , "Lemur" , "Lion"  ) .collect(Collectors.groupingBy( s -> s.charAt( 0 ) // Function<String, K> classifier )); 
 groupingByList: {G=[Giraffe], L=[Lion, Lemur, Lion], M=[Monkey]} 

使用下游收集器收集分组

在前面的示例中,默认情况下,将“下游收集器” toList()应用于Map的值,将每个存储桶的元素收集到List 。 有一个重载版本的groupingBy() ,它允许使用自定义的“下游收集器”来更好地控制生成的Map 。 下面是一个示例,说明如何将特殊的下游收集器counting()用于计数(而不是收集)每个存储区的元素。

 Map<Character, Long> groupingByCounting = Stream.of( "Monkey" , "Lion" , "Giraffe" , "Lemur" , "Lion"  ) .collect(Collectors.groupingBy( s -> s.charAt( 0 ), // Function<String, K> classifier counting() // Downstream collector )); 
 groupingByCounting: {G= 1 , L= 3 , M= 1 } 

这是该过程的说明:

任何收集器都可以用作下游收集器。 特别是,值得注意的是,收集器groupingBy()可以采用下游收集器,该下游收集器也是groupingBy()收集器,从而允许对第一分组操作的结果进行二次分组。 在我们的动物案例中,我们也许可以创建一个Map<Character, Map<Character, Long>> ,其中第一个地图包含具有第一个字符的键,第二个地图包含第二个字符作为键,出现次数作为值。

元素的出现

中间操作filter()是消除与给定谓词不匹配的元素的好方法。 尽管在某些情况下,我们只是想知道是否存在至少一个满足该谓词的元素。 如果是这样,使用anyMatch()会更方便和有效。 在这里,我们寻找数字2的出现:

 boolean containsTwo = IntStream.of( 1 , 2 , 3 ).anyMatch(i -> i == 2 ); 
 containsTwo: true 

计算操作

几个终端操作输出计算结果。 我们可以执行的最简单的计算是count() ,它可以应用于任何
Stream. 例如,它可以用于计算动物数量:

 long nrOfAnimals = Stream.of( "Monkey" , "Lion" , "Giraffe" , "Lemur"  ) .count(); 
 nrOfAnimals: 4 

虽然,某些终端操作仅适用于我们在第一篇文章中提到的特殊Stream实现。 IntStream
LongStreamDoubleStream 。 可以访问此类流,我们可以简单地将所有元素汇总如下:

 int sum = IntStream.of( 1 , 2 , 3 ).sum(); 
 sum: 6 

或者为什么不使用.average()计算整数的平均值:

 OptionalDouble average = IntStream.of( 1 , 2 , 3 ).average(); 
 average: OptionalDouble[ 2.0 ] 

或使用.max()检索最大值。

 int max = IntStream.of( 1 , 2 , 3 ).max().orElse( 0 ); 
 max: 3 

average()一样, max()运算符的结果是Optional ,因此通过声明.orElse(0)我们自动检索该值(如果存在或默认为0)。 如果我们宁愿处理原始返回类型,也可以将相同的解决方案应用于平均示例。

如果我们对所有这些统计数据都感兴趣,那么创建几个相同的流并对每个流应用不同的终端操作是非常麻烦的。 幸运的是,有一个方便的操作称为summaryStatistics() ,它允许将几个常见的统计属性合并到一个
SummaryStatistics对象。

 IntSummaryStatistics statistics = IntStream.of( 1 , 2 , 3 ).summaryStatistics(); 
 statistics: IntSummaryStatistics{count= 3 , sum= 6 , min= 1 , average= 2.000000 , max= 3 } 

练习题

希望您现在熟悉所提供练习的格式。 如果您只是发现了该系列或者最近才感到有点懒惰(也许您也有自己的理由),我们建议您克隆GitHub存储库并开始使用后续材料。 本文的内容足以解决名为MyUnit3Terminal的第三个单元。 相应的Unit3Terminal接口包含JavaDocs,它们描述MyUnit3Terminal方法的预期实现。

 public interface Unit3Terminal { /** * Adds each element in the provided Stream * to the provided Set. * * An input stream of ["A", "B", "C"] and an * empty input Set will modify the input Set * to contain : ["A", "B", "C"] * * @param stream with input elements * @param set to add elements to */  void addToSet(Stream stream, Set set); 
 <br> 

提供的测试(例如Unit3MyTerminalTest)将充当自动评分工具,让您知道您的解决方案是否正确。

下一篇

下一篇文章将展示如何将到目前为止我们积累的所有知识应用于数据库查询。

提示:再见SQL,Hello Streams…直到那时–编码愉快!

s

Per Minborg

Julia·古斯塔夫森(Julia Gustafsson)

翻译自: https://www.javacodegeeks.com/2019/10/become-master-java-streams-terminal-operations.html

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

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

相关文章

matlab多径信道模型,基于matlab的无线多径信道建模与仿真分析

基于matlab的无线多径信道建模与仿真分析 基于MATLAB的无线多径信道建模与仿真分析 摘 要:对于无线通信, 衰落是影响系统性能的重要因素, 而不同形式的衰落对于信号产生的影响 也不相同。本文在阐述移动多径信道特性的基础上, 建立了不同信道模型下多径时延效应的计算 机仿真模…

您的JVM是否泄漏文件描述符-像我的一样?

前言&#xff1a;此处描述的两个问题是在一年前发现并修复的。 本文仅用作历史证明&#xff0c;也是有关解决Java中文件描述符泄漏的初学者指南。 在Ultra ESB中&#xff0c;我们使用内存RAM磁盘文件缓存来进行快速且无垃圾的有效负载处理。 一段时间以前&#xff0c;我们在共…

螺旋桨设计软件_欧洲斥巨资研发的A400M螺旋桨运输机,为啥就没人买啊?| 图说...

A400M是欧洲自行设计、研制和生产的新一代军用运输机&#xff0c;也是欧盟国家进行合作的最大的武器联合研制项目。A400M最大的特点&#xff0c;就是其标志性的8叶弯刀螺旋桨。A400M也是20世纪后服役的为数不多的几个使用涡轮旋桨发动机的军用运输机之一。A400M曾在系列电影《碟…

JAR文件句柄:烦恼后清理!

在Ultra ESB中&#xff0c;我们使用特殊的热交换类加载器 &#xff0c;该加载器使我们可以按需重新加载Java类。 这使我们能够从字面上热交换我们的部署单元 -加载&#xff0c;卸载&#xff0c;使用更新的类重新加载&#xff0c;以及正常地逐步退出-无需重启JVM。 Windows&…

大气校正后的ndvi_Sentinel2 L1C下载、大气校正、重采样

点击蓝字关注我哦1.基本信息(成像仪/重访周期/波段数/分辨率)哨兵2号是高分辨率多光谱成像卫星&#xff0c;携带一枚多光谱成像仪(MSI)&#xff0c;用于陆地监测&#xff0c;可提供植被、土壤和水覆盖、内陆水路及海岸区域等图像&#xff0c;分为2A和2B两颗卫星,哨兵&#xff0…

php strtotime month bug,处理PHP strtotime的BUG

PHP strtotime的BUG处理最近使用了strtotime结合-1 month, 1 month, next month获取上个月或者下个月的日期&#xff0c;不过刚看到一篇文章&#xff0c;才知道原来使用strtotime直接获取日期还是有点小BUGBUG如日期&#xff1a;$today 2020-12-31;echo date("Y-m-d"…

JMetro版本11.5.11和8.5.11发布

你好 具有新JMetro样式的另一个版本&#xff08;深色和浅色版本&#xff09;&#xff1a; 分割菜单按钮 分割窗格 药丸按钮/分段按钮 调整现有样式和错误修复。 继续阅读以获取详细信息。 分割菜单按钮 以下是一个动画&#xff0c;显示了新的“拆分菜单按钮” JMetro浅色…

python xlutils函数,python3:xlrd、xlwt、xlutils处理excel文件

1.xlrd读取excel请参考上篇博客https://www.cnblogs.com/shapeL/p/9075843.html2.xlwt生成excel安装下载&#xff1a;pip install xlwt导入&#xff1a;import xlwt参考&#xff1a;生成excel文件test1.xlsfile_name ../dataconfig/test1.xlswbk xlwt.Workbook() #初始化work…

通过Apache Kafka集成流式传输大数据

从实时实时过滤和处理大量数据&#xff0c;到将日志数据和度量数据记录到不同来源的集中处理程序中&#xff0c;Apache Kafka日益集成到各种系统和解决方案中。 使用CData Sync &#xff0c;可以轻松地将此类解决方案应用于任何CRM&#xff0c;ERP或Analytics软件。 配置Apach…

安卓php推送消息机制,深入剖析Android消息机制原理

在Android中&#xff0c;线程内部或者线程之间进行信息交互时经常会使用消息&#xff0c;这些基础的东西如果我们熟悉其内部的原理&#xff0c;将会使我们容易、更好地架构系统&#xff0c;避免一些低级的错误。在学习Android中消息机制之前&#xff0c;我们先了解与消息有关的…

oracle数据modeling分类,由浅入深 NoSQL的五种主流数据模型

【IT168 技术】本文内容是对《NoSQL Data Modeling Techniques》一文的简单概述&#xff0c;原文对NoSQL的几种数据模型进行了详细深入的讨论。是了解NoSQL数据模型不过错过的全面资料。NoSQL的一些非功能性的特性&#xff0c;比如扩展性、性能以及一致性的讨论&#xff0c;目前…

dederss.php美国与,Dede经验:全站rss/连载和分类首页模板替换

我用的是Dedecms55 utf-8建的站。首先感谢开源工作者们的劳动&#xff0c;其次要感谢使用者写的N多问题与解答。我一个PHP初用者&#xff0c;能在一个月内&#xff0c;一个人把酷猫网http://www.92kcuat.com 建成今天这样&#xff0c;相信很多朋友都可以。当遇到问题时&#xf…

物联网协议之COAP简介及Java实践

目录 前言 一、COAP简介 1、关于COAP 2、COAP特点 3、基于COAP的NB-IoT接入流程 二、CoAP协议JAVA实践 1、californium介绍 2、Java集成 3、Maven 资源引入 4、定义Server端 5、Client调用 6、运行测试 总结 前言 今天平安夜&#xff0c;祝大家圣诞快乐&#xff0c…

bp配置 sap_SAP转储订单之 STO without delivery

在《SAP转储订单STO小结》一文中&#xff0c;介绍了存转储订单(STO)的几种方式&#xff0c;在SAP Library中有相应的描述&#xff1a;1 Stock Transfer Between Plants in One Step2 Stock Transfer Between Plants in TwoSteps3 Stock Transport Order Without Delivery4 Stoc…

[MEGA DEAL] 2020年完整的Java Master Class Bundle(96%)

通过超过62个小时的培训来掌握最流行的编程语言&#xff0c;从而树立良好的开发生涯 嘿&#xff0c;怪胎&#xff0c; 这一周&#xff0c;我们JCG促销专区 &#xff0c;我们有另一个极端的报价 。我们正在提供一个巨大的96&#xff05;off的完整2020 Python编程认证捆绑 。 立…

linux nc命令测试端口,Linux和Windows下的NC(Netcat)命令测试端口连通性

1、Linux OS 环境下(以Centos为例)&#xff0c;使用nc命令分别测试TCP和UDP端口连通性&#xff1a;css安装方法&#xff1a;nginx在客户端和服务器端分别安装nc工具&#xff0c;安装命令以下&#xff1a;webyum install nc1. Linux OS下使用nc命令&#xff0c;实现TCP方式监听服…

javafx css颜色_JavaFX技巧7:使用CSS颜色常量/派生颜色

javafx css颜色在使用FlexCalendarFX时&#xff0c;我不得不定义一组颜色以可视化不同颜色的不同日历的控件。 每个日历不仅提供一种颜色&#xff0c;还提供几种&#xff1a;用于取消选择/选定/悬停状态的背景和文本颜色。 颜色曾在多个地方使用过&#xff0c;但为了简洁起见&…

linux 查看端口 程序,linux开发:Linux下查看端口占用

前段时间有学生问到&#xff0c;怎么查看linux系统中已经被占用的端口&#xff1f;下面就统一给大家解释一下。提到端口&#xff0c;那首先来回顾端口定义&#xff0c;为了区分一台主机接收到的数据包应该转交给哪个任务来进行处理&#xff0c;使用端口号来区别&#xff1b;我们…

十进制小数化为二进制小数的方法是什么_八进制转换成十进制,十进制转换成八进制...

先来看八进制如何转换成十进制。其方法与二进制转换成十进制差不多&#xff1a;按权相加法&#xff0c;即将八进制每位上的数乘以位权&#xff08;如8,64,512….&#xff09;&#xff0c;然后将得出来的数再加在一起。如将72.45转换为十进制。如图1所示来看看十进制转八进制&am…

c++从字符串中提取数字求和_【函数应用】单元格文本内提取数字并求和

本篇的主题是将单元格内一串文本&#xff0c;找出所有数字并求和&#xff0c;如下图。难度较高&#xff0c;新手建议仅了解下&#xff0c;先学会数组运用&#xff0c;再研究此知识点。废话少说&#xff0c;步入正题。重点说明&#xff1a;本篇只针对文本内整数的数字进行提取并…