在我喘不过气来的困惑之后,有什么好的资源可以解释新的Scala 2.8集合库的结构。我很想找到一些有关以下内容的信息:
- 集合类/性状本身(例如
List,Iterable) - 为什么存在Like类(例如
TraversableLike) - 伴随方法有什么作用(例如
List.companion) - 我如何知道
implicit给定点范围内的对象
在我喘不过气来的困惑之后,有什么好的资源可以解释新的Scala 2.8集合库的结构。我很想找到一些有关以下内容的信息:
List,Iterable)TraversableLike)List.companion)implicit给定点范围内的对象Answers:
Martin Odersky的2.8系列演练可能是您的第一个参考。它也得到了建筑笔记的补充,这对那些想要设计自己的收藏的人们特别感兴趣。
在存在任何此类问题之前(实际上,在2.8.0本身发布之前)以其他方式编写了此答案的其余部分。
您可以找到有关此文档的文档Scala SID#3。对Scala 2.7和2.8之间的差异感兴趣的人们也应该关注该领域的其他论文。
我将选择性地引用本文的内容,并补充我的一些想法。马蒂亚斯(Matthias)在decodified.com上还生成了一些图像,可以在此处找到原始SVG文件。
集合的特征实际上有三个层次:一个是可变集合,一个是不可变集合,一个没有对集合进行任何假设。
Scala 2.9中引入了并行,串行和也许并行集合之间的区别。我将在下一节中讨论它们。本节中描述的层次结构专门指非并行集合。
下图显示了Scala 2.8引入的非特定层次结构:

显示的所有元素都是特征。在其他两个层次结构中,还存在直接继承特征的类,以及可以通过隐式转换为包装类而被视为属于该层次结构的类。这些图的图例可以在它们之后找到。
不可变阶层的图表:

可变层次结构图:

传说:

对于那些看不见图像的人,这是集合层次结构的ASCII缩写形式。
Traversable
|
|
Iterable
|
+------------------+--------------------+
Map Set Seq
| | |
| +----+----+ +-----+------+
Sorted Map SortedSet BitSet Buffer Vector LinearSeq
当Scala 2.9引入并行集合时,设计目标之一是使它们的使用尽可能无缝。用最简单的术语来说,一个人可以用一个并行的替换非并行(串行)的集合,并立即获得收益。
但是,由于在那之前所有集合都是串行的,因此许多使用它们的算法都是假设的,并取决于它们是串行的。带有这种假设的方法并行收集将失败。因此,上一节中描述的所有层次结构都要求进行串行处理。
创建了两个新的层次结构来支持并行集合。
并行集合层次具有的性状相同的名称,但前面有Par:ParIterable,ParSeq,ParMap和ParSet。请注意,没有ParTraversable,因为任何支持并行访问的集合都能够支持更强的ParIterable特性。它也不具有序列层次结构中存在的一些更特殊的特征。整个层次结构位于目录下scala.collection.parallel。
实现并行的集合类也各不相同,有ParHashMap和ParHashSet两个可变和不可变的并行收集,加上ParRange与ParVector实施immutable.ParSeq和ParArray执行mutable.ParSeq。
另一个层次还存在镜子串行和并行集合的特点,但有一个前缀Gen:GenTraversable,GenIterable,GenSeq,GenMap和GenSet。这些特征是父母双方并行和串行集合。这意味着采用a的方法Seq不能接收并行集合,但是采用a的方法GenSeq可以用于串行和并行集合。
考虑到这些层次结构的构造方式,为Scala 2.8编写的代码与Scala 2.9完全兼容,并要求串行行为。如果不进行重写,则无法利用并行集合,但是所需的更改很小。
通过调用任何方法都可以将其转换为并行方法par。同样,任何集合都可以通过调用其seq上的方法转换为串行集合。
如果集合已经是请求的类型(并行或串行),则不会进行任何转换。但是,如果调用seq并行集合或par串行集合,则会生成具有所请求特征的新集合。
请勿将seq,与toSeq,Seq从集合的元素返回创建的,与将一个集合变成非并行集合的混淆。调用toSeq并行集合将返回ParSeq,而不是串行集合。
尽管有许多实现类和子特性,但层次结构中还是有一些基本特性,每个特性都提供了更多的方法或更具体的保证,但减少了可以实现它们的类的数量。
在以下小节中,我将简要描述主要特征及其背后的思想。
该特征Traversable与下面描述的特征非常相似,但是有一个限制,即您只能使用一次。也就是说,在a上调用的任何方法都TraversableOnce 可能使其无法使用。
此限制使得在和之间可以共享相同的方法Iterator。这使得Iterator使用而不使用Iterator特定方法的方法实际上可以完全使用任何集合以及迭代器(如果重写为accept)TraversableOnce。
因为TraversableOnce集合和迭代器是统一的,所以它不会出现在先前的图中,后者仅与集合有关。
集合层次结构的顶部是trait Traversable。它唯一的抽象操作是
def foreach[U](f: Elem => U)
该操作旨在遍历集合的所有元素,并将给定的操作f应用于每个元素。该应用仅出于其副作用而完成;实际上,f的任何函数结果都会被foreach丢弃。
可穿越的对象可以是有限的或无限的。无限可遍历对象的一个示例是自然数流Stream.from(0)。该方法hasDefiniteSize指示集合是否可能是无限的。如果hasDefiniteSize返回true,则集合肯定是有限的。如果返回false,则说明集合尚未完全详细说明,因此它可能是无限的或有限的。
此类定义了可以有效地实现foreach(超过40种)的方法。
此特征声明一个抽象方法iterator,该方法返回一个迭代器,该迭代器逐个生成集合的所有元素。中的foreach方法根据Iterable实现iterator。Iterable通常,子类通常使用直接实现来覆盖foreach以提高效率。
类Iterable还向中添加了一些不常用的方法Traversable,只有当iterator可用时才能有效地实现。它们总结如下。
xs.iterator An iterator that yields every element in xs, in the same order as foreach traverses elements.
xs takeRight n A collection consisting of the last n elements of xs (or, some arbitrary n elements, if no order is defined).
xs dropRight n The rest of the collection except xs takeRight n.
xs sameElements ys A test whether xs and ys contain the same elements in the same order
后Iterable有来了三个基本的特征,其继承它:Seq,Set,和Map。这三个都具有apply方法,并且三个都实现了PartialFunction特征,但是apply每种情况下的含义都不同。
我相信的含义Seq,Set而且Map很直观。在它们之后,这些类在特定的实现中分解,这些实现为性能及其所提供的方法提供了特别的保证。此外,还包括一些特质与进一步细化,如LinearSeq,IndexedSeq和SortedSet。
下面的清单可能会得到改善。发表评论并提出建议,我会解决。
Traversable-基本的收藏课。可以用实现foreach。
TraversableProxy-代理Traversable。只是指向self真正的收藏。TraversableView -具有某些非严格方法的Traversable。TraversableForwarder-前锋大多数方法underlying,除了toString,hashCode,equals,stringPrefix,newBuilder,view和所有调用创建相同类型的新的迭代对象。mutable.Traversable和immutable.Traversable-同样的事情Traversable,但限制集合类型。Iterable类,例如MetaData。Iterable-Iterator可以为其创建的集合(通过iterator)。
IterableProxy,IterableView,mutable和immutable.Iterable。Iterator-不是的后代的特征Traversable。定义next和hasNext。
CountedIterator-Iterator定义count,返回到目前为止已看到的元素。BufferedIterator-Defines head,它返回下一个元素而不消耗它。Iterator类,例如Source。Map-一个Iterable的Tuple2,这也提供了用于检索给定的密钥(该元组的第一个元素)的值(该元组的第二个元素)的方法。也延伸PartialFunction。
MapProxy-AProxy代表Map。DefaultMap-一种实现某些Map抽象方法的特征。SortedMap-Map按键已排序的。
immutable.SortMap
immutable.TreeMap-一个实现类immutable.SortedMap。immutable.Map
immutable.MapProxyimmutable.HashMap-immutable.Map通过密钥散列实现的类。immutable.IntMap-实现immutable.Map专用于Int密钥的类。使用基于键的二进制数字的树。immutable.ListMap-immutable.Map通过列表实现的类。immutable.LongMap-实现immutable.Map专用于Long密钥的类。请参阅IntMap。mutable.Map
mutable.HashMap-mutable.Map通过密钥散列实现的类。mutable.ImmutableMapAdaptor-mutable.Map从现有的类实现a的类immutable.Map。mutable.LinkedHashMap -?mutable.ListMap-mutable.Map通过列表实现的类。mutable.MultiMap -一个类,每个键接受多个不同的值。mutable.ObservableMap-甲混入其中,当与混合Map,通过发布事件到观察者Publisher接口。mutable.OpenHashMap -基于开放式哈希算法的类。mutable.SynchronizedMap-一个mixin,应与混合使用,Map以提供带有同步方法的版本。mutable.MapProxy。Seq-一系列元素。假定大小和元素重复定义明确。也延伸PartialFunction。
IndexedSeq -支持O(1)元素访问和O(1)长度计算的序列。
IndexedSeqViewimmutable.PagedSeq-IndexedSeq通过传递给构造函数的函数按需生成元素的实现。immutable.IndexedSeq
immutable.Range -分隔的整数序列,在低端封闭,在高端开放,并带有阶跃。
immutable.Range.Inclusive-Range高端也是如此。immutable.Range.ByOne-Range步骤为1。immutable.NumericRange-通用的版本Range适用于任何版本Integral。
immutable.NumericRange.Inclusive,immutable.NumericRange.Exclusive。immutable.WrappedString,immutable.RichString-包装器,可将aString视为Seq[Char],同时仍保留String方法。我不确定它们之间有什么区别。mutable.IndexedSeq
mutable.GenericArray-Seq基于数组的结构。请注意,“类”Array是Java的Array,它比类更多地是一种内存存储方法。mutable.ResizableArray -基于可调整大小的数组的类使用的内部类。mutable.PriorityQueue,mutable.SynchronizedPriorityQueue-实现优先队列的类-根据Ordering第一个队列和最后一个队列的顺序对元素进行出队列的队列。mutable.PriorityQueueProxy-一个抽象Proxy的PriorityQueue。LinearSeq-线性序列A的性状,具有高效的时间isEmpty,head和tail。
immutable.LinearSeq
immutable.List -不变的单链接列表实现。immutable.Stream-懒惰列表。它的元素仅按需计算,但随后会被记忆(保留在内存中)。理论上它可以是无限的。mutable.LinearSeq
mutable.DoublyLinkedList-具有可变的列表prev,head(elem)和tail(next)。mutable.LinkedList-带有可变head(elem)和tail(next)的列表。mutable.MutableList -在内部用于基于可变列表实现类的类。
mutable.Queue,mutable.QueueProxy-为FIFO(先进先出)操作优化的数据结构。mutable.QueueProxy-AProxy代表mutable.Queue。SeqProxy,SeqView,SeqForwarderimmutable.Seq
immutable.Queue-实现FIFO优化(先进先出)数据结构的类。mutable和immutable队列没有通用的超类。immutable.Stack-实现LIFO优化(后进先出)数据结构的类。两者没有共同的超类mutable immutable堆栈。immutable.Vector -?scala.xml.NodeSeq–扩展的专用XML类immutable.Seq。immutable.IndexedSeq -如上所示。immutable.LinearSeq -如上所示。mutable.ArrayStack-使用数组实现LIFO优化数据结构的类。据说比普通堆栈快得多。mutable.Stack,mutable.SynchronizedStack-实现LIFO优化的数据结构的类。mutable.StackProxy-一个Proxy为mutable.Stack..mutable.Seq
mutable.Buffer -元素的顺序,可以通过追加,添加或插入新成员来更改。
mutable.ArrayBuffer-mutable.Buffer类的实现,具有用于追加,更新和随机访问操作的固定摊销时间。它具有一些专门的子类,例如NodeBuffer。mutable.BufferProxy,mutable.SynchronizedBuffer。mutable.ListBuffer-由列表支持的缓冲区。它提供固定的时间追加和前置,其他大多数操作都是线性的。mutable.ObservableBuffer-混合特性,当与混合时Buffer,可通过Publisher接口提供通知事件。mutable.IndexedSeq -如上所示。mutable.LinearSeq -如上所示。Set -集合是包含最多任何对象的集合。
BitSet -一组存储为位集的整数。
immutable.BitSetmutable.BitSetSortedSet -元素排序的集合。
immutable.SortedSet
immutable.TreeSet-SortedSet基于树的实现。SetProxy-AProxy代表Set。immutable.Set
immutable.HashSet-Set基于元素哈希的实现。immutable.ListSet-Set基于列表的实现。immutable.SetProxy-AProxy为一成不变Set。mutable.Set
mutable.HashSet-Set基于元素哈希的实现。mutable.ImmutableSetAdaptor-Set从不可变实现可变的类Set。LinkedHashSet-Set基于列表的实现。ObservableSet-混合特征,当与混合时Set,可通过Publisher接口提供通知事件。SetProxy-AProxy代表Set。SynchronizedSet-混合特征,当与混合时Set,可通过Publisher接口提供通知事件。这样做是为了实现最大程度的代码重用。具有特定结构(可遍历,映射等)的类的具体通用实现在Like类中完成。然后,用于一般消费的类将覆盖可以优化的所选方法。
类的生成器,即知道如何以类似方法使用的方式创建该类实例的对象 map,是由伴随对象中的方法创建的。因此,为了构建X类型的对象,我需要从X的伴随对象中获得该生成器。不幸的是,在Scala中,无法从X类到X对象。在X的每个实例中定义的方法companion,该方法返回类X的伴随对象。
尽管这种方法在普通程序中可能会有一些用途,但其目标是在集合库中实现代码重用。
您不应该在乎这一点。它们是精确隐式的,因此您无需弄清楚如何使其工作。
这些隐式存在是为了使可以在父类上定义集合上的方法,但仍返回相同类型的集合。例如,map方法是在上定义的TraversableLike,但是如果在上使用,List则会得到List回报。