在Scala集合中,如果想要迭代集合(不返回结果,即对集合的每个元素都产生副作用),可以使用
完成final def foreach(f: (A) ⇒ Unit): Unit
或
final def map[B](f: (A) ⇒ B): SomeCollectionClass[B]
除了可能的延迟映射(*)之外,从最终用户的角度来看,我发现这些调用没有差异:
myCollection.foreach { element =>
doStuffWithElement(element);
}
myCollection.map { element =>
doStuffWithElement(element);
}
鉴于我可以忽略哪些地图输出。我不能想出为什么应该存在两种不同的方法的任何具体原因。当map
似乎包含foreach
的所有功能时,可以使用,事实上,如果一个智能编译器和放大器,我会非常感动。 VM不会优化该集合对象的创建,因为它没有被分配给任何东西,或者在任何地方读取或使用。
所以,问题是 - 我是对的 - 并且没有理由在一个代码中的任何地方拨打foreach
吗?
备注:
(*)惰性映射概念as throughly illustrated in this question可能会改变一些事情并证明foreach
的使用是合理的,但据我所知,一个人特别需要偶然发现{{1}正常
(**)如果一个人不使用一个集合,但正在写一个集合,那么很快就会发现LazyMap
理解语法语法实际上是一种语法糖,可以生成" foreach"调用,即这两行生成完全等效的代码:
for
因此,如果有人关心使用带有for (element <- myCollection) { doStuffWithElement(element); }
myCollection.foreach { element => doStuffWithElement(element); }
语法的集合类的其他人,可能仍然希望实现for
方法。
答案 0 :(得分:13)
我可以想到几个动机:
foreach
是类型为Unit
的方法的最后一行时,您的编译器不会发出警告,但会使用map
(并且您需要-Ywarn-value-discard
上)。有时您使用warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
获得map
但不会使用foreach
。map
则需要更多的认知资源来理解相同的操作map
和foreach
foreach
无法构建新列表,因此效率更高(感谢@Vishnu)答案 1 :(得分:6)
scala> (1 to 5).iterator map println
res0: Iterator[Unit] = non-empty iterator
scala> (1 to 5).iterator foreach println
1
2
3
4
5
答案 2 :(得分:4)
如果可以优化建造机械,我会留下深刻的印象。
scala> :pa
// Entering paste mode (ctrl-D to finish)
implicit val cbf = new collection.generic.CanBuildFrom[List[Int],Int,List[Int]] {
def apply() = new collection.mutable.Builder[Int, List[Int]] {
val b = new collection.mutable.ListBuffer[Int]
override def +=(i: Int) = { println(s"Adding $i") ; b +=(i) ; this }
override def clear() = () ; override def result() = b.result() }
def apply(from: List[Int]) = apply() }
// Exiting paste mode, now interpreting.
cbf: scala.collection.generic.CanBuildFrom[List[Int],Int,List[Int]] = $anon$2@e3cee7b
scala> List(1,2,3) map (_ + 1)
Adding 2
Adding 3
Adding 4
res1: List[Int] = List(2, 3, 4)
scala> List(1,2,3) foreach (_ + 1)