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

Java中的有限生成流-如何创建一个?,java,java-8,java-stream,Java,Java 8,Java Stream,在Java中,可以使用stream.generate(supplier)轻松生成无限流。但是,我需要生成一个最终将完成的流 例如,想象一下,我想要一个目录中所有文件的流。文件的数量可能很大,因此我无法预先收集所有数据并从中创建流(通过collection.stream())。我需要逐段生成序列。但是流显然会在某个时刻结束,像(collect()或findAny())这样的终端操作员需要处理它,因此stream.generate(supplier)在这里不合适 在Java中有没有合理的简单方法可以

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

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

在Java中有没有合理的简单方法可以做到这一点,而不必自己实现整个流接口

我可以想到一个简单的破解方法——使用无限
Stream.generate(supplier)
,并在获取所有实际值时提供null或抛出异常。但是它会破坏标准的流操作符,我只能在我自己的操作符知道这种行为的情况下使用它

澄清

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

解决方案

我要找的代码是

    Iterator it = myCustomIteratorThatGeneratesTheSequence();
    StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT), false);
我刚刚研究了
java.nio.file.Files
list(path)
方法是如何实现的

在Java中有没有合理的简单方法可以做到这一点,而不必自己实现整个流接口

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


工厂方法之后,创建自定义流源而不重新实现流处理管道的最简单方法是对
java.util.Spliterators.AbstractSpliterator进行子类化,并将其传递给
java.util.Stream.StreamSupport.Stream(供应商Kotlin从InputStream创建JsonNode流的代码


    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()
            }
        }
    }


private fun InputStream.toJsonNodeStream():Stream{
returnstreamsupport.stream(
Spliterators.spliteratorUnknownSize(this.toJsonNodeIterator(),Spliterator.ORDERED),
假的
)
}
private fun InputStream.toJsonNodeIterator():迭代器{
val jsonParser=objectMapper.factory.createParser(this)
返回对象:迭代器{
override fun hasNext():Boolean{
var token=jsonParser.nextToken()
while(令牌!=null){
if(token==JsonToken.START\u对象){
返回真值
}
token=jsonParser.nextToken()
}
返回错误
}
重写fun next():JsonNode{
返回jsonParser.readValueAsTree()
}
}
}

这是一个自定义且有限的流:

package org.tom.stream;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;

public class GoldenStreams {
private static final String IDENTITY = "";

public static void main(String[] args) {
    Stream<String> stream = java.util.stream.StreamSupport.stream(new Spliterator<String>() {
        private static final int LIMIT = 25;
        private int integer = Integer.MAX_VALUE;
        {
            integer = 0;
        }
        @Override
        public int characteristics() {
            return Spliterator.DISTINCT;
        }
        @Override
        public long estimateSize() {
            return LIMIT-integer;
        }
        @Override
        public boolean tryAdvance(Consumer<? super String> arg0) {
            arg0.accept(IDENTITY+integer++);
            return integer < 25;
        }
        @Override
        public Spliterator<String> trySplit() {
            System.out.println("trySplit");
            return null;
        }}, false);
    List<String> peeks = new ArrayList<String>();
    List<String> reds = new ArrayList<String>();
    stream.peek(data->{
        peeks.add(data);
    }).filter(data-> {
        return Integer.parseInt(data)%2>0;
    }).peek(data ->{
        System.out.println("peekDeux:"+data);
    }).reduce(IDENTITY,(accumulation,input)->{
        reds.add(input);
        String concat = accumulation + ( accumulation.isEmpty() ? IDENTITY : ":") + input;
        System.out.println("reduce:"+concat);
        return concat;
    });
    System.out.println("Peeks:"+peeks.toString());
    System.out.println("Reduction:"+reds.toString());
}
}
package org.tom.stream;
导入java.util.*;
导入java.util.function.*;
导入java.util.stream.*;
公共级黄金流{
私有静态最终字符串标识=”;
公共静态void main(字符串[]args){
Stream-Stream=java.util.Stream.StreamSupport.Stream(新的拆分器(){
专用静态最终整数限值=25;
private int integer=integer.MAX_值;
{
整数=0;
}
@凌驾
公共int特性(){
返回拆分器.DISTINCT;
}
@凌驾
公共长期估计规模(){
返回极限整数;
}
@凌驾

public boolean tryAdvance(ConsumerI认为我不明白。您是否正在寻找类似于此处的
takeWhile
方法?您是否看过类似于和friends的方法?
openjdk 9
提供了
takeWhile()
@JanXMarek一种方法是使用此答案创建一个
迭代器
,然后使用此答案将
迭代器
转换为一个
。这样迭代器将只在内存中保存一小堆文件,流将被惰性地计算。不过这是一项大量的工作。我强烈建议首先使用check在执行更复杂的
迭代器
之前,先确定
拆分器
的逻辑是否更合适,然后再将其封装在
拆分器
中。参见示例…