Array类 通用数组类定义如下。 final class Array[A](len: Int) extends Seq[A] { def length: Int = len def apply(i: Int): A = ... def update(i: Int, x: A): Unit = ... def elements: Iterator[A] = ... def subArray(from: Int, end: Int): Array[A] = ... def filter(p: A => Boolean): Array[A] = ... def map[B](f: A => B): Array[B] = ... def flatMap[B](f: A => Array[B]): Array[B] = ... } 如果T不是类型参数或抽象类型,类型Array[T]表示宿主系统中的原生数组类型[]T。这种情况下length返回数组的长度,apply表示下标,update表示元素更新。由于apply和update操作(§6.25)的语法糖的存在,以下是Scala和Java/C#中对数组xs操作的对应: Scala Java/C# xs.length xs.length xs(i) xs[i] xs(i) = e xs[i] = e 标准引用类 数组也实现了序列特征scala.Seq,定义了elements方法来返回一个包含数组中所有元素的Iterator 因为在Scala中参数化类型的数组和宿主语言中数组的实现还是有差异的,在处理数组时需要注意一些细小的差别。解释如下。 首先,不像Java或C#中的数组,Scala中的数组不是协变的;也就是说,在Scala中S<:T并不能得出Array[S] <: Array[T]。但是如果在宿主环境中可以将S变为T则可以将S的数组变为T的数组。 举例来说Array[String]并不与Array[Object]一致,即使String与Object一致。然而可以将类型为Array[String]的表达式变为Array[Object]。该转变将会成功,不会抛出ClassCastException。例子如下: val xs = new Array[String](2) // val ys: Array[Object] = xs // **** 错误:不兼容的类型 val ys: Array[Object] = xs.asInstanceOf[Array[Object]] //OK 其次,对于有一个类型参数或抽象类型T作为元素类型的多态数组,其表现形式不同于[]T。然而isInstanceOf和asInstanceOf仍像数组数组使用单态数组的标准表现形式那样正常工作。 val ss = new Array[String](2) def f[T](xs: Array[T]): Array[String] = if(xs.isInstanceOf[Array[String]]) xs.asInstanceOf[Array[String]] else throw new Error(“not an instance”) f(ss) // 返回ss 多态数组的表现形式同样保证了多态数组的创建与期望一致。以下是一个mkArray方法的例子,给定定义了元素且类型为T的序列创建任意类型T的数组。 def mkArray[T](elems: Seq[T]): Array[T] = { val result = new Array[T](elems.length) val I = 0 for (elem <- elems) { result(i) = elem I += 1 } } 注意在Java数组的类型擦除模型下,以上方法不能按照期望的方式工作-实际上它将总是返回一个Object数组。 再次,在Java环境中有一个方法System.arraycopy,有两个对象为参数,指定起始坐标和长度,将元素从一个对象复制到另外一个对象,这两个对象的元素类型必须是兼容的。对于Scala的多态数组该方法不能正常工作,因为他们有不同的表现形式。作为代替应当使用Array类的伴随对象Array.copy方法。该伴随对象也定义了不同的数组构造方法,还定义了提取方法unapplySeq(§8.1.7),提供了数组上的模式匹配。 package scala Scala 标准库 object Array { /** 从src复制元素到dest */ def copy(src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: Int): Unit = ... /** 将参数中所有数组合并为一个 */ def concat[T](xs: Array[T]*): Array[T] = ... /** 创建一个连续的整数数组 */ def range(start: Int, end: Int): Array[Int] = ... /** 用给定元素创建一个数组 */ def apply[A <: AnyRef](xs: A*): Array[A] = ... /** 与上面类似 */ def apply(xs: Boolean*) : Array[Boolean] = ... def apply(xs: Byte*) : Array[Byte] = ... def apply(xs: Short*) : Array[Short] = ... def apply(xs: Char*) : Array[Char] = ... def apply(xs: Int*) : Array[Int] = ... def apply(xs: Long*) : Array[Long] = ... def apply(xs: Float*) : Array[Float] = ... def apply(xs: Double*) : Array[Double] = ... def apply(xs: Unit*) : Array[Unit] = ... /** 创建一个数组,包含一个元素的多个拷贝 */ def make[A](n: Int, elem: A): Array[A] = ... /** 提供数组上的模式匹配 */ def unapplySeq[A](x: Array[A]): Option[Seq[A]] = Some(x) } 示例12.3.1 以下方法复制给定的数组参量并返回初始数组和复制的数组: def duplicate[T](xs: Array[T]) = { val ys = new Array[T](xs.length) Array.copy(xs, 0, ys, 0, xs.length) (xs, ys) } |
更多精彩内容请关注:http://bbs.superwu.cn
关注超人学院java免费学习交流群:
原文地址:http://crxy2013.blog.51cto.com/9922445/1656028