Seq
与Iterable
与Traversable
(或者更深层次地在Seq
的继承体系内)?如何做出这个决定?我们有很多默认返回Seq
的代码(通常是从DB查询和连续转换开始)。我倾向于默认将返回类型设为Traversable
并且当特别需要顺序时使用Seq
。但我没有一个强有力的理由支持这样做。
我非常熟悉每个特质的定义,所以请不要用定义术语来回答。Seq
与Iterable
与Traversable
(或者更深层次地在Seq
的继承体系内)?如何做出这个决定?我们有很多默认返回Seq
的代码(通常是从DB查询和连续转换开始)。我倾向于默认将返回类型设为Traversable
并且当特别需要顺序时使用Seq
。但我没有一个强有力的理由支持这样做。
我非常熟悉每个特质的定义,所以请不要用定义术语来回答。这是一个很好的问题。您需要平衡两个方面:
其中 (1) 要求您对类型不那么具体(例如 Seq
上的 Iterable
),而 (2) 则要求你相反。
即使返回类型只是 Iterable
,您仍然可以返回比如一个 Vector
,因此如果调用者希望获得额外的功能,则可以在其上调用 .toSeq
或 .toIndexedSeq
,并且该操作对于 Vector
来说是便宜的。
作为平衡措施,我会添加第三点:
Seq
。如果可以假设不存在两个相等的对象,请给出一个 Set
。等等。以下是我的经验法则:
Set
、Map
、Seq
、IndexedSeq
List
而不是 Seq
。它允许调用者使用 cons 提取器进行模式匹配。collection.immutable.Set
、collection.immutable.IndexedSeq
)Vector
),而是使用提供相同 API 的通用类型(IndexedSeq
)Iterator
实例,调用者可以轻松地在其上生成一个严格的结构,例如通过对其调用 toList
。IndexedSeq
当然,这是我的个人选择,但我希望听起来很合理。
Seq
。IndexedSeq
。这些是“常识”指导方针。它们简单、实用,在实践中很有效,平衡了原则和性能。原则如下:
Seq
满足以上两个原则。正如在 http://docs.scala-lang.org/overviews/collections/seqs.html 中所描述的:
序列是一种可迭代的集合,具有[有限的]长度和元素的固定索引位置,从 0 开始。
90% 的时间,你的数据是一个 Seq。
其他注意事项:
List
是一种实现类型,因此不应在 API 中使用它。例如,不能将 Vector
作为 List
使用而不经过转换。Iterable
没有定义 length
。 Iterable
在有限序列和潜在无限流之间抽象。大多数时候,人们处理的是有限序列,所以你“拥有一个长度”,Seq
反映了这一点。通常情况下,你实际上不会使用长度。但是,它经常需要,并且很容易提供,因此请使用 Seq
。缺点:
这些“常识”约定存在一些轻微的缺点。
case head :: tail => ...
。可以使用 :+
和 +:
,如此处所述。然而,重要的是,匹配 Nil
仍然像Scala:Pattern matching Seq[Nothing]中所描述的那样起作用。脚注:
Map
,因为问题没有询问相关内容。尽可能将您的方法的返回类型指定为具体类型。这样,如果调用者想要将其保留为SuperSpecializedHashMap
或将其类型化为GenTraversableOnce
,他们可以这样做。这就是编译器默认推断最具体类型的原因。
如果您的函数通过索引访问输入元素,则应将输入指定为IndexedSeq
,因为它是提供有关方法apply
有效实现的保证的最通用类型。
对于抽象成员,相同的规则适用,唯一的区别在于您应该根据计划如何使用它们来指定返回类型,因此它们通常比实现更通用。分类选择Seq
、Set
或Map
是最常见的。
遵循这个规则,您可以保护自己免受非常常见的瓶颈情况的影响,例如项目附加到List
或在Seq
而不是Set
上调用contains
,但您的程序仍然具有良好的自由度,并且在类型选择方面保持一致。
IndexedSeq
与Vector
的区别。从技术上讲,IndexedSeq
不能保证在追加和前置操作时具有O(1)的性能,只有它的默认实现Vector
才能做到。在Scala 2.9.2中,IndexedSeq
使用了高效的Vector
方法。但在2.10.0-M6版本中,这个特性被破坏了,不过似乎已经达成共识,要修复这个问题,使得IndexedSeq
仍然能够保持同样的速度。我写这条评论只是为了提醒大家。有些人会建议使用Vector
而不是IndexedSeq
。 - 0__List
而非Seq
的理由已经过时:"它允许调用者使用 cons 提取器进行模式匹配"。这已经不再相关,因为类似的提取器在Scala 2.10中已经添加到了Seq
中。 - tksfz