Lambda Java流:将用户输入转换为批处理

Lambda Java流:将用户输入转换为批处理,lambda,java-8,java-stream,Lambda,Java 8,Java Stream,我希望流式处理int(来自用户输入)并输出特定长度的列表流-有效地将用户的输入分批处理,然后对其执行其他一些工作。 因此,基本上,对于用户输入:1,2,3,4,5,6,7,8,9我可以将其拆分为这些批,,一旦我收集到3个数字,我想创建一个列表,供下一个处理步骤使用。 为了了解更多信息,我尝试使用Java8中的lamda和流操作来实现这一点 我能找到的唯一相关示例是定制收集器,它做的事情与我想要的非常相似-使用收集器的问题是,我不想等待流的结束,而是在每个批准备就绪时进行处理 有什么简单的方法吗?

我希望流式处理int(来自用户输入)并输出特定长度的列表流-有效地将用户的输入分批处理,然后对其执行其他一些工作。 因此,基本上,对于用户输入:
1,2,3,4,5,6,7,8,9
我可以将其拆分为这些批
,一旦我收集到3个数字,我想创建一个列表,供下一个处理步骤使用。 为了了解更多信息,我尝试使用Java8中的lamda和流操作来实现这一点

我能找到的唯一相关示例是定制收集器,它做的事情与我想要的非常相似-使用收集器的问题是,我不想等待流的结束,而是在每个批准备就绪时进行处理


有什么简单的方法吗?对于这种操作,使用Java8流是否不合适

一般来说,使用Java-8流API解决问题是有问题的。首先,对于并行流来说,将流拆分为固定大小的批处理是不可能的,因为源可能会在某个未知偏移量处拆分任务,因此在一般情况下,在实际处理所有之前的子任务之前,您无法知道当前流元素的索引(这将扼杀并行化的整个思想)。由于流API的思想是以并行和顺序模式相同地工作,因此它根本没有方法将流元素组合成偶数批。有一些第三方解决方案通常会忽略并行流的存在(如
StreamUtils.windowed
),但一般来说,从一开始就生成批而不是转换流会更干净

第二个问题是Java-8中没有现成的工具可以从标准输入中以流的形式获取数字(或者至少是令牌)(只能使用
BufferedReader.lines()
获取行)。在Java-9中,流支持被添加到
Scanner
类(请参阅)中,这会更好一些,但目前您需要执行一些额外的步骤

最后,如果您成功地创建了数量批次流,则需要在标准输入完成后尽快完成它。这是执行
takeWhile
操作的作业,该作业也将仅出现在Java-9中(请参阅)

我可以负担得起涉及我的库的解决方案,尽管我仍然不太喜欢它:

Scanner sc = new Scanner(System.in).useDelimiter("[\n\r,\\s]+");
Iterable<String> iterable = () -> sc;
// Supplier which returns Lists of up to 3 numbers from System.in
Supplier<List<Integer>> triples = () -> StreamEx.of(iterable.spliterator())
        .map(Integer::valueOf).limit(3).toList();
StreamEx.generate(triples).takeWhile(list -> !list.isEmpty())
        // replace with your own stream operations
        // they will be executed as soon as three numbers are entered
        .forEach(System.out::println);
想法是一样的<这里不需要创建代码>拆分器,因为jOOL有
Seq.Seq(迭代器)
方法

最后是protonpack解决方案。我个人不喜欢这个库,但解决方案看起来很短,所以有人可能更喜欢它:

import static com.codepoetics.protonpack.StreamUtils.*;

Scanner sc = new Scanner(System.in).useDelimiter("[\n\r,\\s]+");
Stream<List<Integer>> stream = takeUntil(windowed(
    stream(() -> sc).map(Integer::valueOf), 3, 3), List::isEmpty);
stream.forEach(System.out::println);
import static com.codepostics.protonpack.StreamUtils.*;
Scanner sc=新扫描仪(System.in).useDelimiter(“[\n\r,\\s]+”);
Stream Stream=TAKETILL(窗口化)(
stream(()->sc).map(Integer::valueOf),3,3),List::isEmpty);
stream.forEach(System.out::println);
这里的问题是,由于某种原因,它会延迟批处理,直到形成下一批。此外,如果包含少于3个元素,则不会创建最终批次。该问题在trunc中,但尚未发布

import static com.codepoetics.protonpack.StreamUtils.*;

Scanner sc = new Scanner(System.in).useDelimiter("[\n\r,\\s]+");
Stream<List<Integer>> stream = takeUntil(windowed(
    stream(() -> sc).map(Integer::valueOf), 3, 3), List::isEmpty);
stream.forEach(System.out::println);