Scala语言规范----Array类

Deadly 提交于 2019-12-17 12:04:13

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

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免费学习交流群:

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!