当前位置: 首页 > 网络应用技术

JAVA8流源代码物种(4):一篇文章通过四种终止操作说

时间:2023-03-05 23:28:04 网络应用技术

  Java8流源代码发言(1):以一个简单的示例开始

  JAVA8流源代码规范(2):在-Tepth创建原理的深入分析中

  JAVA8流源代码物种(3):中间操作原理的详细说明

  在上一篇文章中,我们讨论了流的中间操作,并通过分析源代码来了解无状态操作和状态操作之间的区别。如何实现每个中间操作方法。(),map()和其他方法不会立即执行声明的lambda表达式,并且只有调用终止操作才能在流中的元素。在本章中,我们将分析相关的源代码终止操作并深入了解内部原理。

  流API中有一个接口终端代表来终止操作。

  接口上定义了两种通用类型:

  查看方法定义:

  可以通过继承关系可以看出,只有四个类直接实现终端接口。流有很多终止方法,实际上可以将其归类为四个。它可以单独解释:toArray()方法也是终止操作,但与其他方法不同。不使用terminalop。

  现在查看终止操作的终止:

  non -short -circuit操作foreach()foreachordered()toArray()ucuce()min()min()max()max()count()short -circuit操作anymatch()allmatch()allmatch()操作主要包括foreachOp。用deldeop实施了两个终端。实际上,toarray()也是一个非交换的操作,但它不依赖实现终端来完成相应的功能。

  用于遍历流元素的foreach()和foreachorded()方法由ForeachOp的子类完成。

  foreachop的继承结构更加复杂。除上述终端外,还实现了终端链接。他们两个都不应该是陌生人。Sink的上一篇文章有详细的解释。供应商是为呼叫者提供结果的功能接口。

  通过以前的文章和继承结构,我们可以大胆地猜测:Foreachop具有终止操作的能力。在数据处理之前,我们还将是一个接收器,它在中间操作中与接收器实例形成一个接下来的链接列表。elect中的ement。是这样的情况。我们输入源代码进行验证。

  专注于essueuateSequential(),您将在内部调用PipelineHelper#wrapandCopyInto()。查看此方法是否熟悉,是的,是在上一篇文章中多次提到的处理数据的方法。中间操作中的接收器合并为链接列表,然后调用源拆分器将流元素发送到该方法水槽链处理。

  让我们输入此方法以查看,它是在AbstractPipeline中实现的:

  您可以首先调用wrapsink()方法,然后用包装末端的逻辑包装包装接收器:

  在一系列中间操作调用之后,WrapSink()方法在此之前已被多次提及,流是流链接列表。结构如下:

  获得接收器链接列表后,让我们看一下CopyInto()方法如何执行数据处理逻辑:

  因为foreachop是非short -circuit操作,所以它必须采用第一个分支。现在仅分析此逻辑:

  foreach()方法,调用操作函数处理流通过流传递的每个元素。请注意,在并行流中,元素的实际顺序可能不是流的元素的顺序。ReferencePipelinet#foreach():

  foreachOps#makeref()方法:

  创建并返回到OFREF对象,您可以看到它从foreachop继承并实现了Accept()方法,也就是说,当元素到达零件的终止时,将调用lambda表达式。

  最后,让我们看一下AbstractPipipeline#evaluate()。在操作方法的每个终止终止内将调用estuate()方法,以触发流的逻辑执行。在其中,将调用terminalop#evaluequention()方法::

  因此,通过先前的分析,应清楚foreach()方法的过程:首先创建从foreachop继承的ofref对象,然后通过调用AbstractPipipeline#evaluate()方法来调用foreachop#evaluequent()方法。中间操作水槽构建了一个链接列表。最后,通过调用splitrator#foreachRemaining()方法,该元素将元素传递给了接收器链,并且终止了代表接收器的操作的OFREF对象。加工。

  foreachreder()方法,调用操作函数处理流通过流传递的每个元素,还可以确保元素处理顺序与并行流中的流相一致。串行流中的行为与foreach()一致。

  dredop用于流中元素的终止操作。ReDyOp应该是开发人员在工作中最终止的操作,例如:dred(),collect(),max(),依此类推。

  可以看出,降低遗传关系比foreachop更容易。REDYOP不会实现终端键接口。因此,它不包括终止操作的逻辑。它是通过调用重写makeink()方法来获取terminalSink(),然后在每个终止操作方法中查看特定逻辑的AbstractPipipeline#wrapandCopyInto()。

  Reled()具有三种重载方法。我们选择两个关键分析:

  max()方法使用比较比较元素和returns.max()和min()方法的最大值是redair()方法的特殊应用。

  max()方法调用realding()方法,我们可以看到要返回到二进制oprator#maxby():

  逻辑非常简单,也就是说,使用比较器比较当前元素和所有先前元素的较大值,并将其返回为最终结果。

  min()方法使用比较器和返回中的最小值。Logic基本上与max()方法相同。

  以上说,降低器是工作中使用的最终止操作。然后,集合()方法应该是降低操作中最频繁的终止操作方法。也有两种集合()的重载方法。我们专注于带来收集器参数的方法。

  collector中文是指收藏家,该收藏家提供了获取供应商,双调查器和双臂器等功能的方法。我计划在集团,法规,聚合和其他操作中使用收藏家。对收藏家的强大收藏家,我计划在下一章中详细介绍它。在本章中,让我们看看collect()如何使用delidop。

  输入delidops#makeref()方法:

  可以看出,像redain()方法一样,collect()也由dredop实现,但是它返回的yucingsink略有不同。集合()中的状态由供应商在收集器和句柄流中提供。要求覆盖先前的结果,使用Collector#accumulator()方法提供的双张函数用于修改状态的内部数据。

  Stream API提供了收集器接口,使开发人员能够更灵活地处理数据,甚至可以自定义收集器实现类以满足该功能。

  短电路操作和非交换 - 电路操作之间的主要区别在于,如果它是短路操作,那么它可能不一定需要穿越整个流的元素。在某些条件下,可以预先获得结果,并提前结束。短路操作由已实施的Matchop和Findop实施,分别显示了匹配和搜索。

  Matchop是通过谓词函数匹配元素的终止操作。匹配类型包括:全部,任何和无。

  您可以看到该实施基本与其他终端相同,但是在这里应注意两点:

  AbstractPipeline#copyinto():

  AbstractPipeline#copyintowithcancel():

  短电路操作遍历管道链接列表,获取头节点对象,然后调用其foreachWithCancel()方法。当然,begin()和end()方法将在之前和之后调用,并且不会扩展。

  实际上,foreachWithCancel()是调用splitrator#tryadvance()方法以遍历do-nile循环中的元素,但是每个条件都必须在变形之前符合条件:!sink.cancellationRequsted()表示该请求尚未取消。将仔细说出以下解释方法。

  AnyMatch()方法,流中的元素与谓词函数匹配。如果有任何元素匹配,它将返回true,否则返回false。

  让我们输入下面的源代码以分析如何实现此方法。

  相同的例程,通过工厂方法匹配#makEref()创建一个匹配对象:

  MatchSink的父级BooleanTerminalsink:

  您可以看到返回确实是匹配实例,MatchSink是终止操作逻辑的软件包的汇。

  MatchKind定义了三种枚举类型,所有和Nones。以下是任何值的值:field offOnpredIcateMatcher是正确的。如果谓词函数和元素匹配后背,则该过程将终止。返回呼叫聚会的结果是真实的,否则返回的false。

  MatchSink控制短路并通过停止和值变量以及MatchKind枚举来保存匹配结果。

  AllMatch()方法,流中的元素匹配谓词函数。如果任何元素不匹配,它将返回false,否则意味着所有元素都匹配并返回true。注意,此处越多的口感主要是反映此方法和短路操作。

  Reference Pipeline#AllMatch()方法与AnyMatch()相似,但是传递的MatchKind是全类型,因此不会显示它。

  nonematch()方法实际上是allmatch()方法的否定。流中的元素与谓词函数匹配。如果有任何元素匹配,它将返回false,否则所有元素都不匹配并返回true。

  Reference Pipeline#nonematch()方法,创建匹配的实例时,无类型将传递。

  Findop是一个简短的电路操作,可以在流中找到元素。当找到结果时,元素的末端将终止并直接返回结果。

  乍一看,此类中有许多成员变量,控制逻辑应复杂。实际上,在并行处理过程中使用了必须的findfirst和PresentPredicate。其余的与匹配的相似,然后在分析下面的特定方法时详细说明。

  Findfirs()方法返回可选。此可选的值是流的第一个元素。如果流中没有元素,请返回可选的#空()。

  在Reference Pipeline#findfirst()方法中,通过FindOps#makeref()创建Findop对象:

  FindOps#makeref()方法:

  这里的sinksupplier创建了一个findsink.ofref实例:

  findsink.ofref仅实现get()方法来获得搜索结果,但它继承了findSink:

  FindSink通过变量值控制短路过程。接收元素时,请使用值来保存结果并终止遍历。

  findany()方法返回可选。此可选的值是流中的元素。如果流中没有元素,请返回可选的#emptle()。注意在并行流呼叫中,它不一定是流的第一个元素,但是如果它是串行流,则行为与findfirst()相同。可选的值是流的第一个元素。

  本文首先解释了在流呼叫过程中Lambda表达式的lambda表达式的触发时机,并在中间操作呼叫期间解释了链接的列表包装和终止列表的终止过程。基于基于流元素是否在流中进行的基于链接的列表。完整的遍历,将终止操作分为非轴电流操作和短路操作。通过引导所有人阅读源代码,foreachop,delidop,匹配和查找器的实现原则,以及操作方法的每个终止,要实现。

  最后,这并不容易。如果您认为这一系列文章对您有帮助,可以加深对流原理和源代码的理解,请随时毫不犹豫地(?Ω?)来赞美!

  原始:https://juejin.cn/post/7103718952626290695