惰性递归Java8流

惰性递归Java8流,java,java-8,google-cloud-storage,java-stream,Java,Java 8,Google Cloud Storage,Java Stream,我正在使用GoogleCloudJavaAPI从GoogleCloudStorage(GCS)中获取对象。代码如下所示: Storage storage = ... List<StorageObject> storageObjects = storage.objects().list(bucket).execute().getItems(); 其中,takeWhile是从中复制的 这将递归地从所有页面加载存储对象: private Stream<StorageObject&g

我正在使用GoogleCloudJavaAPI从GoogleCloudStorage(GCS)中获取对象。代码如下所示:

Storage storage = ...
List<StorageObject> storageObjects = storage.objects().list(bucket).execute().getItems();
其中,
takeWhile
是从中复制的

这将递归地从所有页面加载存储对象:

private Stream<StorageObject> listGcsPageItems(String bucket, String pageToken) {
    if (pageToken == null) {
        return Stream.empty();
    }


    Storage.Objects.List list = storage.objects().list(bucket);
    if (!pageToken.equals(FIRST_PAGE)) {
        list.setPageToken(pageToken);
    }
    Objects objects = list.execute();
    String nextPageToken = objects.getNextPageToken();
    List<StorageObject> items = objects.getItems();
    return Stream.concat(items.stream(), listGcsPageItems(bucket, nextPageToken));    
}
private Stream listGcsPageItems(字符串bucket,字符串pageToken){
如果(pageToken==null){
返回Stream.empty();
}
Storage.Objects.List List=Storage.Objects().List(bucket);
如果(!pageToken.equals(第一页)){
list.setPageToken(pageToken);
}
Objects=list.execute();
字符串nextPageToken=objects.getNextPageToken();
List items=objects.getItems();
return Stream.concat(items.Stream(),listGcsPageItems(bucket,nextPageToken));
}
其中,
FIRST_PAGE
只是一个“魔法”
String
,它指示方法不设置特定页面(这将导致第一页项目)


这种方法的问题在于它很急迫,即在应用“匹配谓词”之前加载所有页面中的所有项。我希望这是懒惰的(一次一页)。如何实现这一点?

我将实现自定义的
迭代器
供应商
,使当前页面列表和下一页标记保持其内部状态,并逐个生成
存储对象

然后,我将使用以下代码查找第一个匹配项:

Optional<StorageObject> result =
    Stream.generate(new StorageObjectSupplier(...))
        .filter(predicate)
        .findFirst();
可选结果=
生成(新的StorageObjectSupplier(…)
.filter(谓词)
.findFirst();
只有在找到匹配项之前才会调用供应商,即延迟调用

另一种方法是逐页实现供应商,即
类StorageObjectPageSupplier实现供应商
,并使用流API将其展平:

Optional<StorageObject> result =
    Stream.generate(new StorageObjectPageSupplier(...))
        .flatMap(List::stream)
        .filter(predicate)
        .findFirst();
可选结果=
生成(新的StorageObjectPageSupplier(…)
.flatMap(列表::流)
.filter(谓词)
.findFirst();

我将实现定制的
迭代器
供应商
,它将保持当前页面列表和下一页标记处于其内部状态,逐个生成
存储对象
s

然后,我将使用以下代码查找第一个匹配项:

Optional<StorageObject> result =
    Stream.generate(new StorageObjectSupplier(...))
        .filter(predicate)
        .findFirst();
可选结果=
生成(新的StorageObjectSupplier(…)
.filter(谓词)
.findFirst();
只有在找到匹配项之前才会调用供应商,即延迟调用

另一种方法是逐页实现供应商,即
类StorageObjectPageSupplier实现供应商
,并使用流API将其展平:

Optional<StorageObject> result =
    Stream.generate(new StorageObjectPageSupplier(...))
        .flatMap(List::stream)
        .filter(predicate)
        .findFirst();
可选结果=
生成(新的StorageObjectPageSupplier(…)
.flatMap(列表::流)
.filter(谓词)
.findFirst();

我最终使用了第二种方法,效果很好。我最终使用了第二种方法,效果很好。