java –cp ./:_成为Java流大师–第3部分:终端操作

java –cp ./:

比尔·盖茨曾经说过:“我选择一个懒惰的人去做一件困难的事情,因为一个懒惰的人会找到一个简单的方法来做。” 关于流,没有什么比这更真实了。 在本文中,您将学习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)我们自动检索该值的值(如果存在或返回默认值.orElse(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

java –cp ./:

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

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

相关文章

Oracle入门(四)之查询基本信息

一、查询基本信息 &#xff08;1&#xff09; 查询实例服务SQL> show parameter instance name&#xff08;2&#xff09;查询数据库名字SQL> show parameter db_name;&#xff08;3&#xff09;查询数据库名字SQL>select name from v$database;&#xff08;4&#xf…

网络——实现服务器

【0】README 0.1&#xff09; 本文描述部分转自 core java volume 2 &#xff0c; 旨在理解 网络——实现服务器 的基础知识 &#xff1b; 0.2&#xff09; for source code, please visit https://github.com/pacosonTang/core-java-volume/blob/master/coreJavaAdvanced/ch…

image 闪烁 c# ajax updatepanel,Why doesn't asp:UpdatePanel refresh an Image?

问题I have the following UpdatePanel that gets an image from an ashx handler all of which works fine when the page is refreshed. However, when the timer fires, the label is refreshed with current time, but never the image.ImageUrl"~/getImage.ashx?cam…

kafka处理流式数据_通过Apache Kafka集成流式传输大数据

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

Oracle入门(十一)之SQL

一、SQL组成 SQL的组成 核心SQL主要有四个部分&#xff1a; 1、数据定义语言即SQL DDL(Data Definition Language )&#xff0c;用于定义 SQL模式、基本表、视图、索引等结构。 CREATE、ALTER、DROP、REVOKE、GRANT2、数据操纵语言 即SQL DML(Data Manipulation Language)。 数…

常见 Java 字节码 指令 助记符

转自&#xff1a; 常见java字节码 有时候为了能理解JVM对程序所做的优化等&#xff0c;需要查看程序的字节码&#xff0c;因此知道了解一些常见的指令集很重要&#xff01; 指令码 助记符 说明 0x00 nop 什么都不做 0x01 aconst_null 将null推送至栈顶 0x02…

等价关系和等价类_确定Java等价性的新时代?

等价关系和等价类几个月前&#xff0c;我读了一篇题为“确定Java等价性的新时代&#xff1f;”的博客文章。 这在某种程度上与我当时在我那令人沮丧的副项目Java :: Geci中开发的内容非常吻合 。 我建议您暂停阅读&#xff0c;阅读原始文章&#xff0c;然后再返回此处&#xff…

数据结构(一)之链表

一、链表链表是一种物理存储单元上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 链表由一系列结点&#xff08;链表中每一个元素称为结点&#xff09;组成&#xff0c;结点可以在运行时动态生成。每个结点包括两个部分&#xff…

高级数据结构实现——自顶向下伸展树

【0】README 1&#xff09; 本文部分内容转自 数据结构与算法分析&#xff0c;旨在理解 高级数据结构实现——自顶向下伸展树 的基础知识&#xff1b; 2&#xff09; 源代码部分思想借鉴了数据结构与算法分析&#xff0c;有一点干货原创代码&#xff0c;for original source …

测试框架 如何测试私有方法_高效的企业测试–测试框架(5/6)

测试框架 如何测试私有方法本系列文章的这一部分将介绍测试框架以及我在何时以及是否应用它们方面的想法和经验。 关于测试框架的想法 我对大多数测试框架不太满意的原因是&#xff0c;按照我的观点&#xff0c;它们大多增加了语法上的便利性和便利性&#xff0c;但是本质上并…

数据结构(二)之链表反转

一、链表反转 1、反转非递归算法 2、反转递归算法 链表结点&#xff1a; package cn.edu.scau.mk;/**** author MK* param <T>*/ public class Node<T> {private T data;private Node<T> next null;public Node(T data) {this.data data;}public T getD…

web安全测试视频课程专题_有关有效企业测试的视频课程

web安全测试视频课程专题我已经制作了一些有关有效企业测试的视频。 在实际项目中&#xff0c;我仍然认为该主题非常重要。 这是我在测试Enterprise Java项目中的经验以及一些示例。 1.介绍和有效的Maven使用 在此视频中&#xff0c;我将介绍测试过程&#xff0c;并演示如何使…

网络——获取Web数

【0】README 0.1&#xff09; 本文描述转自 core java volume 2&#xff0c; 旨在理解 “网络——获取Web数” 的基础知识&#xff1b; 0.2&#xff09; for source code , please visit https://github.com/pacosonTang/core-java-volume/blob/master/coreJavaAdvanced/chap…

数据结构(三)之单链表反向查找

一、反向查找单链表 1、简单查找 先遍历获取单链表单长度n&#xff0c;然后通过计算得到倒数第k个元素的下标为n-k&#xff0c;然后查找下标为n-k的元素。 2、优化查找 先找到下标为k的元素为记录点p1&#xff0c;然后设置新的记录点p2的下标从0开始&#xff0c;同时遍历两个…

java使用:: 表达式_Java 13:切换表达式的增强功能

java使用:: 表达式您可能还记得我以前的文章&#xff0c;在Java 12中&#xff0c;传统的switch语句得到了增强&#xff0c;因此可以用作表达式。 在Java 13中&#xff0c;对该功能进行了进一步的更改 。 break语句不能再返回值。 相反&#xff0c;您必须使用新的yield语句&…

网络——Base64Encode(转:自定义Base64编码器——Base64Encode)

【0】README 0.1&#xff09; 本文source code 转自 core java volume 2 &#xff0c; 旨在了解 如何定义一个 编码器&#xff0c; 如Base64Encode &#xff1b; 0.2&#xff09;注意&#xff1a; 区别自定义的 Base64Encode 和 java.util.Base64 编码器 0.3&#xff09;fo…

数据结构(四)之单链表查找中间结点

一、查找单链表中间结点 1、简单查找 先遍历获取单链表单长度n&#xff0c;然后通过计算得到中间结点为n/2&#xff0c;然后查找下标为n/2的元素。 2、优化查找 先设置记录点fast、slow&#xff0c;下标均从0开始&#xff0c;fast走两步&#xff0c;slow走一步&#xff0c;同…

java面试常见面试问题_Java面试准备:15个Java面试问题

java面试常见面试问题并非所有的访谈都将重点放在算法和数据结构上—通常&#xff0c;访谈通常只侧重于您声称是专家的语言或技术。在此类访谈中&#xff0c;通常没有任何“陷阱”问题&#xff0c;而是它们要求您利用内存和使用该语言的经验–换句话说&#xff0c;它们测试您对…

网络——提交表单数据(post方式)

【0】README 1&#xff09; 本文文字描述 转自 core java volume 2 &#xff0c; 旨在理解 网络——提交表单数据 的基础知识 &#xff1b; 2&#xff09; for source code, please visit https://github.com/pacosonTang/core-java-volume/tree/master/coreJavaAdvanced/cha…

html5实现最智能大气的公司年会抽奖(源码)

文章目录 1.设计来源1.1 主界面1.3 数据配置1.4 抽奖效果1.5 中奖效果 2.效果和源码配置2.1 动态效果2.2 员工信息配置2.3 奖品信息配置2.4 抽奖音效配置2.5 源代码2.6 项目结构 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/…