Java中的有限生成流 - 如何创建一个?

2022-08-31 21:05:47

在Java中,可以使用轻松生成无限流。但是,我需要生成一个最终将完成的流。Stream.generate(supplier)

例如,想象一下,我想要一个目录中所有文件的流。文件的数量可能很大,因此我无法预先收集所有数据并从中创建流(通过)。我需要逐个生成序列。但是流显然会在某个时候完成,并且像(或)这样的终端运营商需要处理它,所以不适合在这里。collection.stream()collect()findAny()Stream.generate(supplier)

有没有一种合理的简单方法可以在Java中做到这一点,而无需我自己实现整个Stream接口?

我可以想到一个简单的技巧 - 用无限做,并提供null或抛出一个异常,当所有实际值都被取出。但它会破坏标准的流运算符,我只能与我自己的知道这种行为的运算符一起使用它。Stream.generate(supplier)

澄清

评论中的人建议作员。这不是我的意思。如何更好地表达问题...我不是在问如何过滤(或限制)现有流,我是在问如何动态地创建(生成)流,而无需预先加载所有元素,但流的大小有限(事先未知)。takeWhile()

溶液

我一直在寻找的代码是

    Iterator it = myCustomIteratorThatGeneratesTheSequence();
    StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT), false);

我刚刚研究了,该方法是如何实现的。java.nio.file.Fileslist(path)


答案 1

有没有一种合理的简单方法可以在Java中做到这一点,而无需我自己实现整个Stream接口?

一个简单的保证,它将终止。但这并不总是足够强大。.limit()

在工厂方法之后,创建海关流源而不重新实现流处理管道的最简单方法是子类化并将其传递给Streamjava.util.Spliterators.AbstractSpliterator<T>java.util.stream.StreamSupport.stream(Supplier<? extends Spliterator<T>>, int, boolean)

如果您打算使用并行流,请注意,这只会产生次优拆分。如果您对源代码有更多的控制权,则完全实现该接口可以更好。AbstractSpliteratorSpliterator

例如,以下代码段将创建一个流,提供无限序列 1,2,3...

在该特定示例中,您可以使用IntStream.range()

但是流显然会在某个时候完成,像(collect()或findAny())这样的终端运营商需要处理它。

像短路操作这样的短路操作实际上可以在无限流上完成,只要有任何匹配的元素。findAny()

Java 9 引入了 Stream.iterate 来为一些简单情况生成有限流。


答案 2

用于从 InputStream 创建 Stream of JsonNode 的 Kotlin 代码


    private fun InputStream.toJsonNodeStream(): Stream<JsonNode> {
        return StreamSupport.stream(
                Spliterators.spliteratorUnknownSize(this.toJsonNodeIterator(), Spliterator.ORDERED),
                false
        )
    }

    private fun InputStream.toJsonNodeIterator(): Iterator<JsonNode> {
        val jsonParser = objectMapper.factory.createParser(this)

        return object: Iterator<JsonNode> {

            override fun hasNext(): Boolean {
                var token = jsonParser.nextToken()
                while (token != null) {
                    if (token == JsonToken.START_OBJECT) {
                        return true
                    }
                    token = jsonParser.nextToken()
                }
                return false
            }

            override fun next(): JsonNode {
                return jsonParser.readValueAsTree()
            }
        }
    }


推荐