【问题标题】:Can I split a stream into multiple smaller streams我可以将一个流分成多个较小的流吗
【发布时间】:2020-08-19 13:33:48
【问题描述】:

关于流有多个问题,但对于这个用例和在 java 中,没有找到任何问题。

我有大量对象Stream<A> [~100 万个对象]。 StreamA 来自一个文件。

Class A { enum status [Running,queued,Completed], String name }

我想在不使用任何 Collect 语句的情况下将 Stream<A> 拆分为三个流。 Collect 语句将所有内容加载到内存中。

我在这里多次调用 stream.concat 时遇到 StackOverflowException。

Stream.Concat 有 Java Docs 中提到的问题 “实施说明: 从重复连接构造流时要小心。 Accessing an element of a deeply concatenated stream can result in deep call chains, or even StackOverflowException。”

Map<Status, Stream<String>> splitStream = new HashMap<>();
streamA.foreach(aObj -> 
Stream<String> statusBasedStream = splitStream.getOrDefault(aObj.status,Stream.of());
splitStream.put(aObj.status, Stream.concat(statusBasedStream, Stream.of(aObj.name))); 

在 github 中可以使用自定义流来实现串联的选项很少,但希望使用标准库来解决这个问题。

如果数据较小,将采用此处提到的列表方法 (Split stream into substreams with N elements)

【问题讨论】:

  • "Collect 语句将所有内容加载到内存中。"当然可以,但是将所有内容放入地图也会将所有内容加载到内存中。那里没有懒惰。
  • 这感觉像是一个 XY 问题。你真正想达到什么目标?
  • 如果不将它们加载到内存中,您将如何处理状态为 Completed 的近 100 万个名称?
  • @VishwaramSankaran 有 6 个打开的文件有什么问题?这没什么,这是你需要做的。
  • 一百万个字符串并不令人印象深刻。当您将所有字符串收集到 Stream.Builder 实例中时,您甚至没有意识到所有字符串都在内存中,这一事实表明它们没有实际的堆内存问题。你没有说这个Stream&lt;A&gt; 是从哪里来的。此外,还不清楚Stream.concat 会遇到什么问题,当您谈论拆分时,这与concat 所做的完全相反。

标签: java java-8 java-stream


【解决方案1】:

不是问题的确切解决方案,但如果您有关于索引的信息,那么 Stream.skip()Stream.limit() 的组合可以帮助解决这个问题 - 下面是我尝试过的虚拟代码 -

    int queuedNumbers = 100;
    int runningNumbers=200;
    Stream<Object> all = Stream.of();
    Stream<Object> queuedAndCompleted = all.skip(queuedNumbers);
    Stream<Object> queued = all.limit(queuedNumbers);
    Stream<Object> running = queuedAndCompleted.limit(runningNumbers);
    Stream<Object> completed = queuedAndCompleted.skip(runningNumbers);

希望对你有所帮助。

【讨论】:

    猜你喜欢
    • 2013-06-11
    • 1970-01-01
    • 1970-01-01
    • 2013-11-25
    • 1970-01-01
    • 1970-01-01
    • 2021-07-14
    • 2016-09-21
    相关资源
    最近更新 更多