Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 结束一个“问题”;“无限”;满足某些条件时的流_Java_Java Stream - Fatal编程技术网

Java 结束一个“问题”;“无限”;满足某些条件时的流

Java 结束一个“问题”;“无限”;满足某些条件时的流,java,java-stream,Java,Java Stream,我正试图从一个REST风格的web服务中提取数据,该服务以页面形式提供内容 我能知道我已经到达终点的唯一方法是当我要求一页,但没有结果时。我想在那个时候终止流 我已经编写了以下Java代码。第一个函数从web服务中提取一个页面,并将其作为流返回。第二个函数将流平面映射到一个流中 public Stream<ApplicationResponse> getApplications(String token, RestTemplate rt, Integer page, Integer

我正试图从一个REST风格的web服务中提取数据,该服务以页面形式提供内容

我能知道我已经到达终点的唯一方法是当我要求一页,但没有结果时。我想在那个时候终止流

我已经编写了以下Java代码。第一个函数从web服务中提取一个页面,并将其作为流返回。第二个函数将流平面映射到一个流中

public Stream<ApplicationResponse> getApplications(String token, RestTemplate rt, Integer page, Integer pageSize) {
    HttpEntity<String> entity = new HttpEntity<>("parameters", getHeaders(token));
    String url = String.format("%s?PageIndex=%s&PageSize=%s", endpoint, page, pageSize);
    ResponseEntity<ApplicationCollection> ar = rt.exchange(url, HttpMethod.GET, entity, ApplicationCollection.class);
    ApplicationResponse[] res = Objects.requireNonNull(ar.getBody()).getData();

    // Do something here when res is empty, so that the stream ends

    return Arrays.stream(res);
}

public Stream<ApplicationResponse> getApplications(String token, RestTemplate rt) {
    // This function does the right thing, exept when we run out of data!
    return IntStream.iterate(1, i -> i + 1).mapToObj(i -> getApplications(token, rt, i, 500)).flatMap(Function.identity());
}
公共流getApplications(字符串标记、RestTemplate rt、整数页、整数页大小){
HttpEntity=新的HttpEntity(“参数”,getHeader(令牌));
字符串url=String.format(“%s?PageIndex=%s&PageSize=%s”,端点,页面,页面大小);
ResponseEntity ar=rt.exchange(url、HttpMethod.GET、entity、ApplicationCollection.class);
ApplicationResponse[]res=Objects.requirennull(ar.getBody()).getData();
//当res为空时,在此处执行某些操作,以便流结束
返回数组.stream(res);
}
公共流getApplications(字符串令牌、RestTemplate rt){
//这个函数做了正确的事情,当我们用完数据时就可以例外了!
返回IntStream.iterate(1,i->i+1).mapToObj(i->getApplications(token,rt,i,500)).flatMap(Function.identity());
}
问题是,我如何让这一切结束

如果我是用Python写这篇文章的,我会在我知道流中没有什么东西可以放的时候引发StopIteration异常。我能做些类似的事情吗


我能想到的最好的方法是使用null,或者引发一个异常来表示数据的结束,然后将流包装到一个迭代器中,该迭代器知道在接收到信号时停止。但是我还能做什么更惯用的事情吗?

在霍尔格发表评论之后,我尝试了一下,并尝试使用
拆分器
而不是
迭代器
。它确实更简单,因为
next
hasNext
是。。。有点像是组合成了
tryAdvance
?它甚至足够短,只需将其内联到util方法imo中即可

public static Stream<ApplicationResponse> getApplications(String token, RestTemplate rt)
{
    return StreamSupport.stream(new AbstractSpliterator<ApplicationResponse[]>(Long.MAX_VALUE,
                                                                               Spliterator.ORDERED
                                                                                               | Spliterator.IMMUTABLE)
    {
        private int page = 1;

        @Override
        public boolean tryAdvance(Consumer<? super ApplicationResponse[]> action)
        {
            HttpEntity<String> entity = new HttpEntity<>("parameters", getHeaders(token));
            String url = String.format("%s?PageIndex=%s&PageSize=%s", endpoint, page, 500);
            ResponseEntity<ApplicationCollection> ar = rt.exchange(url, HttpMethod.GET, entity,
                                                                   ApplicationCollection.class);
            ApplicationResponse[] res = Objects.requireNonNull(ar.getBody()).getData();

            if (res.length == 0)
                return false;

            page++;
            action.accept(res);
            return true;
        }
    }, false).flatMap(Arrays::stream);
}
publicstaticstreamgetapplications(字符串令牌,rest模板rt)
{
返回StreamSupport.stream(新的AbstractSpliterator(Long.MAX_值,
分路器
|拆分器(不可变)
{
私有int页=1;
@凌驾

公共布尔型优先权(Consumer…如果内部函数引发异常,有没有一种方法可以正常处理该异常并允许流结束?不是在您希望从操作中获得结果时。尝试使用
Spliterator
而不是
Iterator
。您会发现它实际上更简单。@Holger这种简单性即将到来事实上,这是一种“做”的单一方法,
tryAdvance
?回来感觉很好,顺便说一句:)@Eugene是一个简单的方法,具有与任务匹配的直接逻辑。相反,两个
迭代器
方法需要额外检查是否已经存在查询值。此外,在创建
时,
迭代器
必须包装到
拆分器中。此答案的解决方案使用了一个附加值通过创建
Iterable
调用
spliterator()的nal迂回
这将在
拆分器处结束。Spliterator Unknownsize
您也可以直接调用它,但在一开始实现
拆分器时它不是必需的。@Holger当我开始尝试直接实现拆分器时,它在
tryAdvance
周围相当大。我找到了抽象实现成功地缩短了它。记得重写
forEachRemaining
,但发现在这种情况下它实际上没有提供任何好处。请执行所选参数(
特征
估计大小
)有意义。我是否正确理解了
trySplit
的实现,因为
Long。MAX_VALUE
确保它不会并行化?我只是注意到了这个注释,不过迟回答总比不回答好。位必须与二进制或,即
拆分器组合。有序的|拆分器。不可变的
。不提供
大小的de>和
Long.MAX_值作为估计值具有“未知大小”的含义,但这并不意味着没有拆分支持。继承的实现将调用您的
tryAdvance
,将元素缓冲到一个数组中,并返回一个基于数组的拆分器。这没有什么错,您的代码仍然只由一个线程调用。这只是意味着,如果您海因的行动很繁重。
public class ResponseIterator
    implements Iterator<Stream<ApplicationResponse>>
{
    private int                   page = 1;
    private String                token;
    private RestTemplate          rt;

    private ApplicationResponse[] next;

    private ResponseIterator(String token, RestTemplate rt)
    {
        this.token = token;
        this.rt = rt;
    }

    public static Stream<ApplicationResponse> getApplications(String token, RestTemplate rt)
    {
        Iterable<Stream<ApplicationResponse>> iterable = () -> new ResponseIterator(token, rt);
        return StreamSupport.stream(iterable.spliterator(), false).flatMap(Function.identity());
    }

    @Override
    public boolean hasNext()
    {
        if (next == null)
        {
            next = getNext();
        }
        return next.length != 0;
    }

    @Override
    public Stream<ApplicationResponse> next()
    {
        if (next == null)
        {
            next = getNext();
        }
        Stream<ApplicationResponse> nextStream = Arrays.stream(next);
        next = getNext();
        return nextStream;
    }

    private ApplicationResponse[] getNext()
    {
        HttpEntity<String> entity = new HttpEntity<>("parameters", getHeaders(token));
        String url = String.format("%s?PageIndex=%s&PageSize=%s", endpoint, page, 500);
        ResponseEntity<ApplicationCollection> ar = rt.exchange(url, HttpMethod.GET, entity,
                                                               ApplicationCollection.class);
        ApplicationResponse[] res = Objects.requireNonNull(ar.getBody()).getData();
        page++;
        return res;
    }
}