我在玩 Java8 的流和CompletableFuture
s。我预先存在的代码有一个类,它接受一个 URL 并下载它:
public class FileDownloader implements Runnable {
private URL target;
public FileDownloader(String target) {
this.target = new URL(target);
}
public void run() { /* do it */ }
}
现在,这个类从另一个发出的部分List<String>
(单个主机上的多个目标)获取它的信息。
我已将周围的代码切换为CompletableFuture
:
public class Downloader {
public static void main(String[] args) {
List<String> hosts = fetchTargetHosts();
for (String host : hosts) {
HostDownloader worker = new HostDownloader(host);
CompletableFuture<List<String>> future =
CompletableFuture.supplyAsync(worker);
future.thenAcceptAsync((files) -> {
for (String target : files) {
new FileDownloader(target).run();
}
});
}
}
public static class HostDownloader implements Supplier<List<String>> {
/* not shown */
}
/* My implementation should either be Runnable or Consumer.
Please suggest based on a idiomatic approach to the main loop.
*/
public static class FileDownloader implements Runnable, Consumer<String> {
private String target;
public FileDownloader(String target) {
this.target = target;
}
@Override
public void run() { accept(this.target); }
@Override
public void accept(String target) {
try (Writer output = new FileWriter("/tmp/blubb")) {
output.write(new URL(target).getContent().toString());
} catch (IOException e) { /* just for demo */ }
}
}
}
现在,这感觉不自然。我正在产生一个String
s 流,而我FileDownloader
一次消耗其中一个。是否有现成的东西可以使我的单个值Consumer
与List
s 一起使用,还是我在for
这里陷入循环?
我知道将循环移入accept
并制作 a是微不足道的Consumer<List<String>>
,这不是重点。