在我喘不过气来的困惑之后,有什么好的资源可以解释新的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.MapProxy
immutable.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)长度计算的序列。
IndexedSeqView
immutable.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
,SeqForwarder
immutable.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.BitSet
mutable.BitSet
SortedSet
-元素排序的集合。
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
回报。