Java8流-增量收集/部分减少/间歇映射/…这到底叫什么?
我正在处理一个可能无限的数据元素流,这些数据元素遵循以下模式:Java8流-增量收集/部分减少/间歇映射/…这到底叫什么?,java,dictionary,java-8,java-stream,reduce,Java,Dictionary,Java 8,Java Stream,Reduce,我正在处理一个可能无限的数据元素流,这些数据元素遵循以下模式: E1 E2富 E3巴 ... En-1巴 EN 也就是说,一个s流,在我可以将它们映射到对象模型之前,必须将其累积在缓冲区中 目标:将流聚合为流,而无需在无限流上进行收集 在英语中,代码类似于“一旦看到开始标记,就开始缓冲。缓冲,直到看到结束标记,然后准备返回旧缓冲,并准备一个新缓冲。返回旧缓冲。” 我当前的实现形式如下: Data<String>.stream() .map(function
E1
E2富
E3巴
...
En-1巴
EN
也就是说,一个s流,在我可以将它们映射到对象模型之前,必须将其累积在缓冲区中
目标:将流
聚合为流
,而无需在无限流上进行收集
在英语中,代码类似于“一旦看到开始标记,就开始缓冲。缓冲,直到看到结束标记,然后准备返回旧缓冲,并准备一个新缓冲。返回旧缓冲。”
我当前的实现形式如下:
Data<String>.stream()
.map(functionReturningAnOptionalPresentOnlyIfObjectIsComplete)
.filter(Optional::isPresent)
Data.stream()
.map(函数返回NoOptionalPresentonlyFobjectisComplete)
.filter(可选::isPresent)
我有几个问题:
.map()
的讨论都是关于1:1映射的。每一个关于.reduce的讨论)都是关于n:1还原的。关于.collect()
的每一次讨论都谈到了作为终端操作的累积…).collectunlconditiontheapplyfinisher(收集器、条件、完成器)
..的候选者)谢谢 为了避免混乱,可以在映射之前进行筛选
Data<String>.stream()
.filter(text -> canBeConvertedToObject(text))
.map(text -> convertToObject(text))
Data.stream()
.filter(文本->canBeConvertedToObject(文本))
.map(文本->转换对象(文本))
它在无限流上工作得非常好,只构造需要构造的对象。它还避免了创建不必要的可选对象的开销。不幸的是,Java8流API中没有部分reduce操作。然而,这样的操作是在我的库中实现的,它增强了标准的Java8流。所以你的任务可以这样解决:
Stream<ObjectDefinedByStrings> result =
StreamEx.of(strings)
.groupRuns((a, b) -> !b.contains("<start mark>"))
.map(stringList -> constructObjectDefinedByStrings());
我为这个部分缩减提出了另外两个用例: 1.解析SQL和PL/SQL(Oracle过程)语句 SQL语句的标准分隔符是分号(
;
)。它将普通SQL语句彼此分离。但若您有PL/SQL语句,那个么分号将语句中的运算符彼此分开,而不仅仅是整个语句
解析同时包含普通SQL和PL/SQL语句的脚本文件的方法之一是首先用分号将它们拆分,然后如果特定语句以特定关键字开头(DECLARE
,BEGIN
,等等),则按照PL/SQL语法规则将此语句与下一个语句连接起来
顺便说一下,这不能通过使用StreamEx
partial reduce操作来实现,因为它们只测试两个相邻的元素。因为您需要了解从初始PL/SQL关键字元素开始的以前的流元素,以确定是将当前元素包括到部分缩减中还是应该完成部分缩减。在这种情况下,可变部分还原可以在收集器保存已收集元素的信息和一些谓词
仅测试收集器本身(如果应完成部分还原)或BiPredicate
同时测试收集器和当前流元素的情况下使用
理论上,我们谈论的是使用流管道思想实现LR(0)或LR(1)解析器(请参阅)。LR解析器可用于解析大多数编程语言的语法
解析器是一个具有堆栈的有限自动机。对于LR(0)自动机,其转换仅取决于堆栈。在LR(1)自动机的情况下,它取决于堆栈和流中的下一个元素(理论上可以有LR(2)、LR(3)等自动机查看2、3等。确定转换的下一个元素,但实际上所有编程语言在语法上都是LR(1)语言)
要实现解析器,应该有一个收集器,其中包含有限自动机堆栈,并对是否达到该自动机的最终状态进行谓词测试(这样我们就可以停止缩减)。对于LR(0),它应该是谓词
测试收集器
本身。对于LR(1),它应该是BiPredicate
测试收集器和流中的下一个元素(因为转换取决于堆栈和下一个符号)
因此,要实现LR(0)解析器,我们需要如下类似的东西(T
是流元素类型,A
是同时包含有限自动机堆栈和结果的累加器,R
是每个解析器工作形成输出流的结果):
注意:在这种情况下,BiPredicate
应先测试元素,然后它将被累加器消耗。请记住,LR(1)解析器正在窥视下一个元素以确定转换。因此,如果空累加器拒绝接受下一个元素(供应商和下一个流元素刚刚创建的空累加器上,BiPredicate
返回true,表示部分减少结束),则可能存在潜在的异常
2.基于流元素类型的条件批处理
在执行SQL语句时,我们希望将相邻的数据修改(DML)语句合并到单个批处理中(请参阅JDBCAPI),以提高总体性能。但我们不想批量查询。所以我们需要条件批处理(而不是像中那样的无条件批处理)
对于这种特定情况,可以使用StreamEx
部分reduce操作,因为如果由BiPredicate
测试的两个相邻元素都是DML语句,则应将它们包含在批处理中。所以我们不需要知道以前的批量收集历史
但我们可以增加任务的复杂性,并说批次应该受到大小的限制。比如说,不超过100个DML语句i
Stream<ObjectDefinedByStrings> result =
StreamEx.of(strings)
.collapse((a, b) -> !b.contains("<start mark>"), Collectors.joining())
.map(joinedString -> constructObjectDefinedByStrings());
<R,A> Stream<R> Stream<T>.parse(
Collector<T,A,R> automataCollector,
Predicate<A> isFinalState)
<R,A> Stream<R> Stream<T>.parse(
BiPredicate<A, T> isFinalState
Collector<T,A,R> automataCollector)