首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java :将用户输入转换为批处理

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

Stack Overflow用户
提问于 2015-11-25 20:30:16
回答 1查看 858关注 0票数 4

我想要流it (从用户输入)并输出一个特定长度的列表流--有效地将用户的输入批处理成批,然后对其执行其他一些工作。因此,基本上,对于用户输入:1,2,3,4,5,6,7,8,9,只要我收集到3个数字,我就可以将它分割成这些批<1,2,3> , <4,5,6> , <7,8,9>,我想为下一个处理步骤创建一个列表。我试图使用lamda和java 8中的流操作来实现这一点,以便更多地了解它。

我能找到的唯一相关示例是这个带有自定义收集器的http://www.nurkiewicz.com/2014/07/grouping-sampling-and-batching-custom.html,它执行与我想要的非常相似的事情--使用收集器的问题是,我不想等待流的结束,而是在准备就绪时处理每一批。

有什么简单的方法吗?在这种操作中使用Java 8流是否不合适?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-11-26 05:11:04

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

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

最后,如果您成功地创建了数字流批,则需要在标准输入完成后尽快完成它。这是takeWhile操作的工作,它也将只出现在Java-9中(参见JDK-8071597)。

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

代码语言:javascript
运行
复制
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);

这里使用的StreamEx的主要特性是StreamEx.takeWhile,它是Java-9 Stream.takeWhile的后端。

如果您更喜欢使用jOOL,则会更简单:

代码语言:javascript
运行
复制
Scanner sc = new Scanner(System.in).useDelimiter("[\n\r,\\s]+");
Supplier<List<Integer>> triples = () -> Seq.seq(sc).map(Integer::valueOf).limit(3).toList();
Seq.generate(triples).limitUntil(List::isEmpty)
    .forEach(System.out::println);

想法是一样的。Spliterator创建在这里是不必要的,因为jOOL有Seq.seq(Iterator)方法。

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

代码语言:javascript
运行
复制
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);

这里的问题是,由于某种原因,它会将批处理延迟到下一批生成。此外,如果它的元素少于3个,则不会创建最后的批处理。这个问题是集群中的fixed,但尚未发布。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33925889

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档