本文介绍了CompletableFutures和基于内部值的过滤的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在有点困惑,所以我有一个方法应该返回CompletableFuture<List<A>>

I'm in a bit of confusion right now, so I have a method that should return CompletableFuture<List<A>>

里面的方法是:

CompletableFuture<List<String>> toReturn = asyncCall().thenApply(....)
.thenCompose(listOfStuff -> convertToList(listOfStuff.stream().map(
     key -> asyncCall2(key)
        .thenApply(optionalValue -> optionalValue.orElse(null))
).collect(Collectors.toList()));

convertToList()只需加入期货即可将CompletableFuture<List<ComputableFuture<A>>>转换为CompletableFuture<List<A>>

and convertToList() simply joins futures to convert CompletableFuture<List<ComputableFuture<A>>> into CompletableFuture<List<A>>

基本上我的意图是过滤从optionalValue.orElse(null)中出现的空值,并且在收集所有内容以列出最后一行之前很容易进行过滤,但是如果我在.collect之前使用它,它将CompletableFutures

Basically my intention is to filter null values that emerge from optionalValue.orElse(null) And it would be easy to do filter before collecting it all to list in the last line, but if I use it just before .collect it is working over CompletableFutures

我怀疑我的代码中可以进行很多重组.

I suspect there's a lot of restructuring I can do in my code.

private<T> CompletableFuture<List<T>> convertToList(List<CompletableFuture<T>> toConvert) {
    return CompletableFuture.allOf(toConvert.toArray(new CompletableFuture[toConvert.size()]))
            .thenApply(v -> toConvert.stream()
                    .map(CompletableFuture::join)
                    .collect(Collectors.toList())
            );
}

推荐答案

最好的方法可能是更改convertToList(),以便它不返回列表的前一个,而是返回流的前一个:

The best way would probably be to change convertToList() so that it does not return a future of list, but of stream instead:

private <T> CompletableFuture<Stream<T>> convertToFutureOfStream(List<CompletableFuture<T>> toConvert) {
    return CompletableFuture.allOf(toConvert.stream().toArray(CompletableFuture[]::new))
            .thenApply(
                    v -> toConvert.stream()
                            .map(CompletableFuture::join)
            );
}

这将更加可重用,因为该方法将允许更好的链接,并且不会强制调用者使用列表,同时仍然允许通过简单的collect轻松获得列表.

This will be more reusable as the method will allow better chaining and will not force the caller to work with a list, while still allowing to easily get a list with a simple collect.

然后您可以简单地过滤该流以删除空的可选内容:

You can then simply filter that stream to remove empty optionals:

CompletableFuture<List<String>> toReturn = asyncCall()
    .thenCompose(listOfStuff -> convertToFutureOfStream(
            listOfStuff.stream()
                    .map(this::asyncCall2)
                    .collect(Collectors.toList())
        )
        .thenApply(stream ->
                stream.filter(Optional::isPresent)
                        .map(Optional::get)
                        .collect(Collectors.toList())
        )

    );

您甚至可以通过更改convertToFutureOfStream()以将流也作为参数来进一步改善此问题:

You can even improve this a little further by changing convertToFutureOfStream() to take a stream as argument as well:

private <T> CompletableFuture<Stream<T>> convertToFutureOfStream(Stream<CompletableFuture<T>> stream) {
    CompletableFuture<T>[] futures = stream.toArray(CompletableFuture[]::new);
    return CompletableFuture.allOf(futures)
            .thenApply(v -> Arrays.stream(futures).map(CompletableFuture::join));
}

(不幸的是,由于泛型类型的数组,这会引发未经检查的分配警告)

(unfortunately this raises an unchecked assignment warning because of the array of generic types)

然后给出

CompletableFuture<List<String>> toReturn = asyncCall()
    .thenCompose(listOfStuff -> convertToFutureOfStream(
                listOfStuff.stream().map(this::asyncCall2)
            )
        .thenApply(stream ->
                stream.filter(Optional::isPresent)
                        .map(Optional::get)
                        .collect(Collectors.toList())
        )

    );

这篇关于CompletableFutures和基于内部值的过滤的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 20:27
查看更多