7.5 日志和打印消息

假设你要在集合上进行大量操作,你要调试代码,你希望看到每一步操作的结果是什么。可以在每一步打印出集合中的值,这在流中很难做到,因为一些中间步骤是惰性求值的。

让我们通过第3章介绍的命令式版本的国际报告程序,看看如何记录中间值。考虑到读者可能已经忘记这个程序,我们再来解释一下这个程序的意图,该程序找出了专辑上每位艺术家来自哪个国家。在例7-16中,我们将找到的国家信息记录到日志中。

例7-16 记录中间值,以便调试for循环

  1. Set<String> nationalities = new HashSet<>();
  2. for (Artist artist : album.getMusicianList()) {
  3. if (artist.getName().startsWith("The")) {
  4. String nationality = artist.getNationality();
  5. System.out.println("Found nationality: " + nationality);
  6. nationalities.add(nationality);
  7. }
  8. }
  9. return nationalities;

现在可以使用forEach方法打印出流中的值,这同时会触发求值过程。但是这样的操作有个缺点:我们无法再继续操作流了,流只能使用一次。如果我们还想继续,必须重新创建流。例7-17展示了这样的代码会有多难看。

例7-17 使用forEach记录中间值,这种方式有点幼稚

  1. album.getMusicians()
  2. .filter(artist -> artist.getName().startsWith("The"))
  3. .map(artist -> artist.getNationality())
  4. .forEach(nationality -> System.out.println("Found: " + nationality));
  5. Set<String> nationalities
  6. = album.getMusicians()
  7. .filter(artist -> artist.getName().startsWith("The"))
  8. .map(artist -> artist.getNationality())
  9. .collect(Collectors.<String>toSet());