4

这些似乎实际上是等效的:

scala> ("asd" zip "zxc").toMap
res62: scala.collection.immutable.Map[Char,Char] = Map(a -> z, s -> x, d -> c)

scala> Map(("asd" zip "zxc"): _*)
res63: scala.collection.immutable.Map[Char,Char] = Map(a -> z, s -> x, d -> c)

但是,现实生活中的差异是什么?哪个更惯用?运行时性能会有什么不同吗?

我敢肯定,对于其他类似的构造对,可能会提出相同/类似的问题,因此请随时给出更一般/抽象的答案:)

4

2 回答 2

3

由于这些方法的定义位置,两者之间存在真正的区别:

  • apply 构造函数在目标集合的同伴中定义:

    object Coll {
      def apply[T](els: T*): Coll[T] = ???
    }
    

    这意味着它除了 a of 元素之外绝对没有关于输入的信息Seq,因此它只是遍历该序列并构建 a Coll

  • 另一方面,toSeq, toArray, ... 是在集合中定义的,这意味着它们具有有关其内部结构的所有额外信息。

通常,您可以依靠toXXX方法在需要时进行短路,或者返回一些有意义的专用集合。

作为一个愚蠢的例子,考虑:

List(1,2,3).toSeq // toSeq returns `this`, there is no overhead
// vs.
Seq(List(1,2,3): _*) // this will copy that list into a new one...

这会变得更糟,如果您将该列表替换为Stream.continually(1)...

于 2013-09-08T22:10:25.023 回答
0

我个人更喜欢第一个变体,因为它更清晰易读。两者在性能或其他特性上没有实际差异。在第一种情况下,您创建一个索引 seq,然后在第二种情况下将其转换为映射,您使用这个 seq 提取器 sintax:_*这是 Scala 最好的部分。就像 Odersky 教授告诉许多许多人一样,为不同的问题提供设计解决方案是 Scala 设计的一部分。所以在这种情况下,你可以选择任何。但正如我告诉你的那样,第一个更清晰易懂,把核心符号编程留给Scalaz=)

于 2013-09-08T20:37:49.577 回答