本文概述了如何使用 Azure SDK for Java 分页和迭代功能高效高效地处理大型数据集。
Azure Java SDK 中的客户端库提供的许多操作会返回多个结果。 在这些情况下,Azure Java SDK 定义了一组可接受的返回类型,以确保开发人员体验通过一致性最大化。 使用的返回类型为 PagedIterable
(用于同步 API)和 PagedFlux
(用于异步 API)。 API 因用例的不同而略有不同,但从概念上讲,它们具有相同的要求:
可以轻松地单独迭代集合中的每个元素,而无需手动分页或跟踪延续令牌。
PagedIterable
和PagedFlux
都通过迭代反序列化为给定类型T
的分页响应来简化此任务。PagedIterable
实现Iterable
接口,并提供一个 API 来接收Stream
,同时PagedFlux
提供一个Flux
。 在所有情况下,分页行为都是透明的,并且只要仍有结果需要迭代,迭代就会继续。可以逐页明确地进行迭代。 这样做可以让你更清楚地了解何时发出请求,并允许访问每页响应信息。
PagedIterable
和PagedFlux
都具有一些方法,这些方法将返回适合按页面而非单个元素进行迭代的类型。
本文在 Java Azure SDK 同步 API 和异步 API 之间进行拆分。 使用同步客户端时,你将看到同步迭代 API,在处理异步客户端时会看到异步迭代 API。
同步分页和迭代
本部分介绍同步 API。
迭代单个元素
如前所述,最常见的用例是逐个循环访问每个元素,而不是每个页面。 以下代码示例展示如何使用 PagedIterable
API 来运用适合自己的迭代样式实现此功能。
使用 for-each 循环
由于 PagedIterable
实现了 Iterable
,您可以通过以下示例来迭代元素:
PagedIterable<Secret> secrets = client.listSecrets();
for (Secret secret : secrets) {
System.out.println("Secret is: " + secret);
}
使用流
由于 PagedIterable
其上定义了一个 stream()
方法,因此可以调用该方法以使用标准 Java 流 API,如以下示例所示:
client.listSecrets()
.stream()
.forEach(secret -> System.out.println("Secret is: " + secret));
使用迭代器
因为 PagedIterable
实现了 Iterable
,它还具有一个 iterator()
方法,以允许使用 Java 迭代器编程样式,如以下示例所示:
Iterator<Secret> secrets = client.listSecrets().iterator();
while (it.hasNext()) {
System.out.println("Secret is: " + it.next());
}
遍历页面
使用各个页面时,可以逐页处理,例如,当需要 HTTP 响应信息或续页标记对于保留迭代历史至关重要时。 无论你是按页面循环访问还是按每个项进行迭代,性能还是对服务进行的调用次数都没有任何差异。 基础实现按需加载下一页,如果随时取消订阅 PagedFlux
,则不会进一步调用该服务。
使用 for-each 循环
调用 listSecrets()
时,会得到一个 PagedIterable
,它具有 iterableByPage()
API。 此 API 生成一个 Iterable<PagedResponse<Secret>>
而不是一个 Iterable<Secret>
。 PagedResponse
提供响应元数据和继续令牌的访问权限,如以下示例所示:
Iterable<PagedResponse<Secret>> secretPages = client.listSecrets().iterableByPage();
for (PagedResponse<Secret> page : secretPages) {
System.out.println("Response code: " + page.getStatusCode());
System.out.println("Continuation Token: " + page.getContinuationToken());
page.getElements().forEach(secret -> System.out.println("Secret value: " + secret))
}
还有一个 iterableByPage
重载,它接受延续令牌。 如果以后要返回到同一迭代点,则可以调用此重载。
使用流
以下示例演示该方法如何执行与上面所示相同的操作。 此 API 还具有延续令牌重载,用于稍后返回到相同的迭代点。
client.listSecrets()
.streamByPage()
.forEach(page -> {
System.out.println("Response code: " + page.getStatusCode());
System.out.println("Continuation Token: " + page.getContinuationToken());
page.getElements().forEach(secret -> System.out.println("Secret value: " + secret))
});
异步观察页面和单个元素
本部分介绍异步 API。 在异步 API 中,网络调用发生在与调用 subscribe()
的主线程不同的线程中。 这意味着主线程可能会在结果可用之前终止。 由你负责确保在异步操作完成之前,应用程序不会退出。
观察各个元素
以下示例展示了 PagedFlux
API 如何让你异步观察单个元素。 有多种方法可以订阅 Flux 类型。 有关详细信息,请参阅 Reactor 3 参考指南中的创建 Flux 或 Mono 并订阅它的简单方法。 此示例是其中有三个 lambda 表达式的一种,分别用于使用者、错误使用者和完整使用者。 拥有这三种情况是一种很好的做法,但在某些情况下,只需要有使用者,并且可能还有错误使用者。
asyncClient.listSecrets()
.subscribe(secret -> System.out.println("Secret value: " + secret),
ex -> System.out.println("Error listing secrets: " + ex.getMessage()),
() -> System.out.println("Successfully listed all secrets"));
观察页面
以下示例展示了 PagedFlux
API 如何让你异步观察每个页面,同样是通过使用 byPage()
API 并提供使用者、错误使用者和完成使用者。
asyncClient.listSecrets().byPage()
.subscribe(page -> {
System.out.println("Response code: " + page.getStatusCode());
System.out.println("Continuation Token: " + page.getContinuationToken());
page.getElements().forEach(secret -> System.out.println("Secret value: " + secret))
},
ex -> System.out.println("Error listing pages with secret: " + ex.getMessage()),
() -> System.out.println("Successfully listed all pages with secret"));
后续步骤
现在你已经熟悉了适用于 Java 的 Azure SDK 中的分页和迭代,请考虑查看 Azure SDK for Java 中的长时间运行操作。 长时间运行的操作是那些运行时间比大多数正常 HTTP 请求更长的操作,通常是因为它们需要在服务器端进行一些额外的处理。