Effective Java(3rd)-Item58 与传统的f

2018-09-18  本文已影响0人  难以置信的优雅

  正如在第45项中所讨论的,一些任务最好使用流来完成,其他任务最好使用迭代。下面是一个传统的for循环来遍历一个集合:


image.png

  这些习惯用法比while循环更好(item57 ),但是它们并不完美。迭代器和索引变量都很混乱—您只需要元素。此外,它们代表了出错的机会。迭代器在每个循环中出现三次,索引变量出现四次,这使您有很多机会使用错误的变量。如果这样做,就不能保证编译器会捕捉到问题。最后,这两个循环非常不同,引起了对容器类型的不必要注意,并且增加了更改该类型的(小的)麻烦。

  for-each循环(官方称为“enhanced for语句”)解决了所有这些问题。它通过隐藏迭代器或索引变量来消除混乱和出错的机会。由此产生的习惯用法同样适用于集合和数组,从而简化了将容器的实现类型从一种转换为另一种的过程:


image.png

  当您看到冒号(:)时,请将其读作“in”。因此,上面的循环读作“for each element e in elements”。使用for-each循环不会降低性能,即使对于数组也是如此:它们生成的代码本质上与手工编写的代码相同。
  当涉及到嵌套迭代时,for-each循环相对于传统for循环的优势甚至更大。下面是人们在进行嵌套迭代时经常犯的一个错误:

image.png

  如果你没有发现这个bug,不要感到难过。许多专业程序员都曾犯过这样或那样的错误。问题是,对于外部集合(suit),下一个方法在迭代器上调用了太多次。它应该从外部循环调用,因此每花色调用一次,但它是从内部循环调用的,因此每一张牌调用一次。在suit用完之后,循环抛出NoSuchElementException。
  如果您真的很不幸,并且外部集合的大小是内部集合大小的倍数(可能因为它们是相同的集合),循环将正常终止,但是它不会执行您想要的操作。例如,考虑一下打印一对骰子的所有可能卷的错误尝试:


image.png

  程序不会抛出异常,但它只打印6个“double”(从“ONE ONE”到“six six”),而不是预期的36个组合。
  要修复这些例子中的错误,您必须在外部循环的范围内添加一个变量来保存外部元素:


image.png

  相反,如果使用嵌套for-each循环,问题就会消失。生成的代码尽可能简洁:


image.png

  不幸的是,有三种常见的情况是你不能分别使用的:

上一篇下一篇

猜你喜欢

热点阅读