使用Java流上的筛选操作的结果调用函数的最佳方法是什么
我想知道最好的方法是使用新的Java8流API读取文件,通过模式匹配过滤输入流,然后将结果传递给使用匹配中的组的函数。我认为这是不可能的,因为流操作是无状态的,模式匹配器中的组无法传递到流处理器中的下一步 那么,假设我有这个 stream.filter->pattern.matcher.matches()) 是否可以将调用添加到从matches()中获取s或(最好是)组的函数中?差不多 stream.filter->pattern.matcher.matches()).ifTrue->myfunc 我基本上希望避免将所有匹配项收集到内存中的数据结构,因为我不知道流有多大。假设我有一个巨大的文件,我想构造并序列化一个封装模式匹配器组的对象。我不想在一个数据结构中保存所有匹配项并进行必要的处理,那么对文件进行操作的最佳方式是什么,这样我就可以处理一行并限制内存消耗,同时也允许并行处理文件 对这些行进行迭代并一次一个地处理是否更好?这是否等同于流上forEach()的终端操作?在我的用例中,我可能不关心不能对终端操作进行并行化的副作用,但我很好奇forEach在并行处理过程中出现问题的一般情况 谢谢。你可以在溪流边 返回一个由该流的元素组成的流,在从结果流中消耗元素时,对每个元素执行提供的操作 这是一个中间操作 流是完整的,但您可以使用lambda表达式(a使用Java流上的筛选操作的结果调用函数的最佳方法是什么,java,lambda,java-8,java-stream,Java,Lambda,Java 8,Java Stream,我想知道最好的方法是使用新的Java8流API读取文件,通过模式匹配过滤输入流,然后将结果传递给使用匹配中的组的函数。我认为这是不可能的,因为流操作是无状态的,模式匹配器中的组无法传递到流处理器中的下一步 那么,假设我有这个 stream.filter->pattern.matcher.matches()) 是否可以将调用添加到从matches()中获取s或(最好是)组的函数中?差不多 stream.filter->pattern.matcher.matches()).ifTrue->myfun
使用者
)执行操作
你的要求有点奇怪。如果调用
matches
则意味着整个字符串都匹配,因此元素就是匹配项
在流上请求.ifTrue(s->myfunc(s))
方法是没有意义的,事实上,它让我想知道过滤器的作用。如果在筛选
之后链接一个操作,它将仅应用于匹配项,因为这是筛选
的目的
stream.filter(s -> pattern.matcher(s).matches()).peek(s -> myfunc(s))
因此stream.filter->pattern.matcher.matches()).forEach(s->myfunc(s))
是该作业的正确工具,它既不意味着数据收集,也不意味着多线程问题。如果函数myfunc
本身没有线程问题,filter(…).forEach(…)
可以并行运行而不会出现问题
值得注意的是,模式
有一个方法。它使用find
而不是matches
,但这可以通过向模式添加锚来解决:
Stream.of("a", "b", "ab", "bb", "aaa", "bab")
.filter(Pattern.compile("^a*$").asPredicate())
.forEach(System.out::println);
将打印
a
aaa
并且将与并行
一起工作(只有顺序可能会更改)
如果您确实需要匹配器的状态,则必须提供选项
首先创建匹配器
,然后应用过滤器
:
Pattern p=Pattern.compile("b(a+)b");
Stream.of("a", "b", "bab", "bb", "aa", "baaab")//.parallel()
.map(p::matcher)
.filter(Matcher::matches)
.mapToInt(m->m.end(1)-m.start(1))
.forEach(System.out::println);
使用flatMap
并用结果Stream
Pattern p=Pattern.compile("b(a+)b");
Stream.of("a", "b", "bab", "bb", "aa", "baaab")//.parallel()
.flatMap(s-> { Matcher m=p.matcher(s);
return m.matches()? Stream.of(m.group(1)): Stream.empty(); })
.mapToInt(String::length)
.forEach(System.out::println);
两者都将打印1
和3
,并且对并行执行是安全的;将forEach
与并行流一起使用可能会改变顺序,仅此而已。如果您对源订单感兴趣,可以使用。将已接受的答案更改为该答案,因为我觉得它更准确地讨论了与当前问题相关的流的行为。事实上,我确实使用了forEach()而不是peek(),因为我需要一个终端操作来强制处理文件。我所寻找的是一种处理无限文件流的方法,而使用流API是不可能的。我最终选择了commons io Tailer库,因为它提供了我想要的行为,即处理每一行并执行一个处理程序来处理它。同时,我希望在将新行写入文件时保持管道打开以处理新行。