扩展Scala集合:一种基于Array的索引练习

Pen*_*gin 6 scala scala-2.8 scala-collections

作为练习,我想将Scala数组集合扩展到我自己的OneBasedArray(做你期望的,索引从1开始).由于这是一个不可变的集合,我想让它在调用filter/map等时返回正确的类型.

我已经在这里,这里这里阅读了资源,但我很难理解如何将其转换为数组(或者除了示例中的集合之外的其他集合).我是否在这种结构的正确轨道上?

class OneBasedArray[T] 
  extends Array[T] 
  with GenericTraversableTemplate[T, OneBasedArray]
  with ArrayLike[T, OneBasedArray]
Run Code Online (Sandbox Code Playgroud)

是否还有其他资源可以帮助解释扩展集合?

ped*_*rla 5

顺便说一下,我不认为Array是Scala中的集合.


Kev*_*ght 2

Array 不是典型的 Scala 集合...它只是一个 Java 数组,通过隐式转换使其看起来像一个集合。

考虑到 Java 数组混乱的差异,如果没有极其令人信服的理由,你真的不想使用它们,因为它们是潜在错误的来源。

(请参见此处: http: //www.infoq.com/presentations/Java-Puzzlers

像这样创建一个基于 1 的集合也不是一个好主意,因为您无法知道有多少其他集合方法依赖于序列基于 0 的假设。因此,为了安全地执行此操作(如果确实必须),您需要添加一种新方法,使默认方法保持不变:

class OneBasedLookup[T](seq:Seq) {
  def atIdx(i:Int) = seq(i-1)
}

implicit def seqHasOneBasedLookup(seq:Seq) = new OneBasedLookup(seq)

// now use `atIdx` on any sequence.
Run Code Online (Sandbox Code Playgroud)

更安全的是,您可以创建一个Map[Int,T],其中索引是基于 1 的

(Iterator.from(1) zip seq).toMap
Run Code Online (Sandbox Code Playgroud)

这可以说是最“正确”的解决方案,尽管它也会带来最高的性能成本。