【scala原理系列】ArrayOps原理用法示例源码详解

本文围绕Scala的ArrayOps展开,它是数组的包装器,通过隐式转换由数组类自动转换而来。借助隐式转换函数,可将数组转换为ArrayOps对象,从而使用求和、排序等丰富方法操作数组,扩展了数组类型的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【scala原理系列】scala ArrayOps原理用法示例源码详解

简介

ArrayOps作为Array的包装器,提供了所有索引序列中的操作。 在需要时,数组的实例会隐式转换为这个类。

这个类和WrappedArray的区别在于,调用filtermap等转换方法将产生一个数组, 而WrappedArray将保持为WrappedArray

原理

ArrayOps是Scala中的一个隐式转换类,它是由scala.Array类自动转换而来的。当我们对一个数组对象调用方法时,Scala编译器会自动将其转换为ArrayOps类型,以便能够使用更多的操作和方法。

具体来说,ArrayOps类是通过隐式转换函数wrapIntArray定义的,该函数接受一个Array[Int]类型的参数,并返回一个ArrayOps[Int]类型的对象。在Scala的标准库中,还有其他类似的隐式转换函数,如longArrayOpsfloatArrayOps等,它们分别用于将数组类型转换为相应的ArrayOps对象。

通过将数组转换为ArrayOps对象,我们可以使用ArrayOps提供的丰富方法和操作符来处理数组,而不仅限于原始的数组操作。这些方法和操作符包括求和、最大值、最小值、排序、复制到另一个数组、切片、转换为其他类型的数组、添加元素、并行操作、展平、转置、拆分等。

总之,ArrayOps是通过隐式转换实现的,它扩展了数组类型的功能,使得我们可以更方便地对数组进行操作和处理。

隐式转换源码

object Predef extends LowPriorityImplicits with DeprecatedPredef {
  implicit def genericArrayOps[T](xs: Array[T]): ArrayOps[T] = (xs match {
    case x: Array[AnyRef]  => refArrayOps[AnyRef](x)
    case x: Array[Boolean] => booleanArrayOps(x)
    case x: Array[Byte]    => byteArrayOps(x)
    case x: Array[Char]    => charArrayOps(x)
    case x: Array[Double]  => doubleArrayOps(x)
    case x: Array[Float]   => floatArrayOps(x)
    case x: Array[Int]     => intArrayOps(x)
    case x: Array[Long]    => longArrayOps(x)
    case x: Array[Short]   => shortArrayOps(x)
    case x: Array[Unit]    => unitArrayOps(x)
    case null              => null
  }).asInstanceOf[ArrayOps[T]]
  
implicit def booleanArrayOps(xs: Array[Boolean]): ArrayOps[Boolean] = new ArrayOps.ofBoolean(xs)
implicit def byteArrayOps(xs: Array[Byte]): ArrayOps[Byte]          = new ArrayOps.ofByte(xs)
implicit def charArrayOps(xs: Array[Char]): ArrayOps[Char]          = new ArrayOps.ofChar(xs)
implicit def doubleArrayOps(xs: Array[Double]): ArrayOps[Double]    = new ArrayOps.ofDouble(xs)
implicit def floatArrayOps(xs: Array[Float]): ArrayOps[Float]       = new ArrayOps.ofFloat(xs)
implicit def intArrayOps(xs: Array[Int]): ArrayOps[Int]             = new ArrayOps.ofInt(xs)
implicit def longArrayOps(xs: Array[Long]): ArrayOps[Long]          = new ArrayOps.ofLong(xs)
implicit def refArrayOps[T <: AnyRef](xs: Array[T]): ArrayOps[T]    = new ArrayOps.ofRef[T](xs)
implicit def shortArrayOps(xs: Array[Short]): ArrayOps[Short]       = new ArrayOps.ofShort(xs)
implicit def unitArrayOps(xs: Array[Unit]): ArrayOps[Unit]          = new ArrayOps.ofUnit(xs)
}

方法总结

方法名描述
copyToArray将当前数组的元素复制到另一个数组中。
slice对数组进行切片操作,返回指定范围内的子数组。
toArray将数组转换为另一种类型的数组。
:+在数组末尾添加一个元素,并返回一个新的数组。
+:在数组开头添加一个元素,并返回一个新的数组。
par将数组转换为并行数组。
flatten将二维数组展平成一维数组。
transpose转置二维数组。
unzip将数组中的元素对拆分成两个数组。
unzip3将数组中的元素三元组拆分成三个数组。

示例

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.collection.parallel.mutable.ParArray

object ArrayOpsDemo {
  def main(args: Array[String]): Unit = {
    // 创建一个整数数组
    val array: Array[Int] = Array(1, 2, 3, 4, 5)

    // 将数组转换为ArrayOps对象,以便使用ArrayOps的方法
    val arrayOps: mutable.ArrayOps[Int] = array

    // 使用ArrayOps的方法操作数组
    val sum: Int = arrayOps.sum
    val max: Int = arrayOps.max
    val min: Int = arrayOps.min
    val sorted: Array[Int] = arrayOps.sorted
    val slicedArray: Array[Int] = arrayOps.slice(1, 4)
    val toArray: Array[Any] = arrayOps.toArray[Any]
    val appendedArray: Array[Int] = arrayOps.:+(6)
    val prependedArray: Array[Int] = arrayOps.+:(0)
    val parArray: ParArray[Int] = arrayOps.par
    val flattenedArray: Array[Int] = Array(Array(1, 2), Array(3, 4)).flatten
    val transposedArray: Array[Array[Int]] = Array(Array(1, 2), Array(3, 4)).transpose
    val unzipped: (Array[Int], Array[Int]) = Array((1, 2), (3, 4)).unzip
    val unzipped3: (Array[Int], Array[Int], Array[Int]) = Array((1, 2, 3), (4, 5, 6)).unzip3

    // 打印结果
    println("数组元素之和:" + sum)
    println("数组最大值:" + max)
    println("数组最小值:" + min)
    println("排序后的数组:" + sorted.mkString(", "))
    println("切片后的数组:" + slicedArray.mkString(", "))
    println("转换为其他类型的数组:" + toArray.mkString(", "))
    println("在末尾添加元素后的数组:" + appendedArray.mkString(", "))
    println("在开头添加元素后的数组:" + prependedArray.mkString(", "))
    println("并行数组:" + parArray.mkString(", "))
    println("展平后的数组:" + flattenedArray.mkString(", "))
    println("转置后的二维数组:")
    transposedArray.foreach(row => println(row.mkString(", ")))
    println("拆分后的两个数组:" + unzipped._1.mkString(", ") + ", " + unzipped._2.mkString(", "))
    println("拆分后的三个数组:" + unzipped3._1.mkString(", ") + ", " + unzipped3._2.mkString(", ") + ", " + unzipped3._3.mkString(", "))

    // 创建一个可变数组
    val arrayBuffer: ArrayBuffer[Int] = ArrayBuffer(6, 7, 8, 9, 10)

    // 将可变数组转换为ArrayOps对象
    var arrayBufferOps: mutable.ArrayOps[Int] = arrayBuffer.toArray

    // 使用ArrayOps的方法操作可变数组
    arrayBufferOps.foreach(println)
    arrayBufferOps = arrayBufferOps :+ 11
    arrayBufferOps = 9 +: arrayBufferOps

    // 打印修改后的可变数组
    println("修改后的可变数组:" + arrayBufferOps.mkString(", "))
  }
}

//数组元素之和:15
//数组最大值:5
//数组最小值:1
//排序后的数组:1, 2, 3, 4, 5
//切片后的数组:2, 3, 4
//转换为其他类型的数组:1, 2, 3, 4, 5
//在末尾添加元素后的数组:1, 2, 3, 4, 5, 6
//在开头添加元素后的数组:0, 1, 2, 3, 4, 5
//并行数组:1, 2, 3, 4, 5
//展平后的数组:1, 2, 3, 4
//转置后的二维数组:
//1, 3
//2, 4
//拆分后的两个数组:1, 3, 2, 4
//拆分后的三个数组:1, 4, 2, 5, 3, 6
//6
//7
//8
//9
//10
//修改后的可变数组:9, 6, 7, 8, 9, 10, 11

源码分析

/**
 * 这个类作为`Array`的包装器,提供了所有索引序列中的操作。
 * 在需要时,数组的实例会隐式转换为这个类。
 *
 * 这个类和`WrappedArray`的区别在于,调用`filter`和`map`等转换方法将产生一个数组,
 * 而`WrappedArray`将保持为`WrappedArray`。
 *
 * @since 2.8
 *
 * @tparam T   数组中元素的类型。
 *
 * @define Coll `Array`
 * @define orderDependent
 * @define orderDependentFold
 * @define mayNotTerminateInf
 * @define willNotTerminateInf
 */
sealed trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomParallelizable[T, ParArray[T]] {

  private def elementClass: Class[_] =
    repr.getClass.getComponentType

  override def copyToArray[U >: T](xs: Array[U], start: Int, len: Int) {
    val l = len min repr.length min (xs.length - start)
    if (l > 0) Array.copy(repr, 0, xs, start, l)
  }

  override def slice(from: Int, until: Int): Array[T] = {
     val reprVal = repr
     val lo = math.max(from, 0)
     val hi = math.min(math.max(until, 0), reprVal.length)
     val size = math.max(hi - lo, 0)
     val result = java.lang.reflect.Array.newInstance(elementClass, size)
     if (size > 0) {
      Array.copy(reprVal, lo, result, 0, size)
     }
     result.asInstanceOf[Array[T]]
  }

  override def toArray[U >: T : ClassTag]: Array[U] = {
    val thatElementClass = implicitly[ClassTag[U]].runtimeClass
    if (elementClass eq thatElementClass)
      repr.asInstanceOf[Array[U]]
    else
      super.toArray[U]
  }

  def :+[B >: T: ClassTag](elem: B): Array[B] = {
    val currentLength = repr.length
    val result = new Array[B](currentLength + 1)
    Array.copy(repr, 0, result, 0, currentLength)
    result(currentLength) = elem
    result
  }

  def +:[B >: T: ClassTag](elem: B): Array[B] = {
    val currentLength = repr.length
    val result = new Array[B](currentLength + 1)
    result(0) = elem
    Array.copy(repr, 0, result, 1, currentLength)
    result
  }

  override def par = ParArray.handoff(repr)

  /** 将二维数组展平,将所有行连接成一个单独的数组。
   *
   * @tparam U        行元素的类型。
   * @param asTrav    将数组中的元素转换为行 - 类型为`U`的数组。
   * @return          通过连接该数组的行而获得的数组。
   */
  def flatten[U](implicit asTrav: T => scala.collection.Traversable[U], m: ClassTag[U]): Array[U] = {
    val b = Array.newBuilder[U]
    b.sizeHint(map{case is: scala.collection.IndexedSeq[_] => is.size case _ => 0}.sum)
    for (xs <- this)
      b ++= asTrav(xs)
    b.result()
  }

  /** 转置一个二维数组。
   *
   * @tparam U       行元素的类型。
   * @param asArray  将数组中的元素转换为行 - 类型为`U`的数组。
   * @return         通过替换该数组的元素以表示行获得的数组。
   */
  def transpose[U](implicit asArray: T => Array[U]): Array[Array[U]] = {
    val bb: Builder[Array[U], Array[Array[U]]] = Array.newBuilder(ClassTag[Array[U]](elementClass))
    if (isEmpty) bb.result()
    else {
      def mkRowBuilder() = Array.newBuilder(ClassTag[U](elementClass.getComponentType))
      val bs = asArray(head) map (_ => mkRowBuilder())
      for (xs <- this) {
        var i = 0
        for (x <- asArray(xs)) {
          bs(i) += x
          i += 1
        }
      }
      for (b <- bs) bb += b.result()
      bb.result()
    }
  }

  /** 将一对数组转换为第一个元素数组和第二个元素数组。
   *
   * @tparam T1    元素对的第一半的类型
   * @tparam T2    元素对的第二半的类型
   * @param asPair 断言这个数组的元素类型是一对的隐式转换。
   * @param ct1    T1类型参数的类标签,用于创建Array[T1]的实例
   * @param ct2    T2类型参数的类标签,用于创建Array[T2]的实例
   * @return       包含分别是该数组的元素对的第一半和第二半的一对数组。
   */
  def unzip[T1, T2](implicit asPair: T => (T1, T2), ct1: ClassTag[T1], ct2: ClassTag[T2]): (Array[T1], Array[T2]) = {
    val a1 = new Array[T1](length)
    val a2 = new Array[T2](length)
    var i = 0
    while (i < length) {
      val e = apply(i)
      a1(i) = e._1
      a2(i) = e._2
      i += 1
    }
    (a1, a2)
  }

  /** 将三元组的数组转换为三个数组,一个包含三元组中每个位置的元素。
   *
   * @tparam T1      三元组中第一个元素的类型
   * @tparam T2      三元组中第二个元素的类型
   * @tparam T3      三元组中第三个元素的类型
   * @param asTriple 断言这个数组的元素类型是三元组的隐式转换。
   * @param ct1    T1类型参数的类标签,用于创建Array[T1]的实例
   * @param ct2    T2类型参数的类标签,用于创建Array[T2]的实例
   * @param ct3    T3类型参数的类标签,用于创建Array[T3]的实例
   * @return         一个由该数组的每个元素三元组的第一、第二和第三个元素组成的三个数组。
   */
  def unzip3[T1, T2, T3](implicit asTriple: T => (T1, T2, T3), ct1: ClassTag[T1], ct2: ClassTag[T2],
    ct3: ClassTag[T3]): (Array[T1], Array[T2], Array[T3]) = {
    val a1 = new Array[T1](length)
    val a2 = new Array[T2](length)
    val a3 = new Array[T3](length)
    var i = 0
    while (i < length) {
      val e = apply(i)
      a1(i) = e._1
      a2(i) = e._2
      a3(i) = e._3
      i += 1
    }
    (a1, a2, a3)
  }

  def seq = thisCollection
}

/**
 * `ArrayOps`的伴生对象。
 *
 * @since 2.8
 */
object ArrayOps {

  /** 包含引用类型的数组的`ArrayOps`类。 */
  final class ofRef[T <: AnyRef](override val repr: Array[T]) extends AnyVal with ArrayOps[T] with ArrayLike[T, Array[T]] {

    override protected[this] def thisCollection: WrappedArray[T] = new WrappedArray.ofRef[T](repr)
    override protected[this] def toCollection(repr: Array[T]): WrappedArray[T] = new WrappedArray.ofRef[T](repr)
    override protected[this] def newBuilder = new ArrayBuilder.ofRef[T]()(ClassTag[T](repr.getClass.getComponentType))

    def length: Int = repr.length
    def apply(index: Int): T = repr(index)
    def update(index: Int, elem: T) { repr(index) = elem }
  }

  /** 包含`Byte`的数组的`ArrayOps`的子类。 */
  final class ofByte(override val repr: Array[Byte]) extends AnyVal with ArrayOps[Byte] with ArrayLike[Byte, Array[Byte]] {

    override protected[this] def thisCollection: WrappedArray[Byte] = new WrappedArray.ofByte(repr)
    override protected[this] def toCollection(repr: Array[Byte]): WrappedArray[Byte] = new WrappedArray.ofByte(repr)
    override protected[this] def newBuilder = new ArrayBuilder.ofByte

    def length: Int = repr.length
    def apply(index: Int): Byte = repr(index)
    def update(index: Int, elem: Byte) { repr(index) = elem }
  }

  /** 包含`Short`的数组的`ArrayOps`的子类。 */
  final class ofShort(override val repr: Array[Short]) extends AnyVal with ArrayOps[Short] with ArrayLike[Short, Array[Short]] {

    override protected[this] def thisCollection: WrappedArray[Short] = new WrappedArray.ofShort(repr)
    override protected[this] def toCollection(repr: Array[Short]): WrappedArray[Short] = new WrappedArray.ofShort(repr)
    override protected[this] def newBuilder = new ArrayBuilder.ofShort

    def length: Int = repr.length
    def apply(index: Int): Short = repr(index)
    def update(index: Int, elem: Short) { repr(index) = elem }
  }

  /** 包含`Char`的数组的`ArrayOps`的子类。 */
  final class ofChar(override val repr: Array[Char]) extends AnyVal with ArrayOps[Char] with ArrayLike[Char, Array[Char]] {

    override protected[this] def thisCollection: WrappedArray[Char] = new WrappedArray.ofChar(repr)
    override protected[this] def toCollection(repr: Array[Char]): WrappedArray[Char] = new WrappedArray.ofChar(repr)
    override protected[this] def newBuilder = new ArrayBuilder.ofChar

    def length: Int = repr.length
    def apply(index: Int): Char = repr(index)
    def update(index: Int, elem: Char) { repr(index) = elem }
  }

  /** 包含`Int`的数组的`ArrayOps`的子类。 */
  final class ofInt(override val repr: Array[Int]) extends AnyVal with ArrayOps[Int] with ArrayLike[Int, Array[Int]] {

    override protected[this] def thisCollection: WrappedArray[Int] = new WrappedArray.ofInt(repr)
    override protected[this] def toCollection(repr: Array[Int]): WrappedArray[Int] = new WrappedArray.ofInt(repr)
    override protected[this] def newBuilder = new ArrayBuilder.ofInt

    def length: Int = repr.length
    def apply(index: Int): Int = repr(index)
    def update(index: Int, elem: Int) { repr(index) = elem }
  }

  /** 包含`Long`的数组的`ArrayOps`的子类。 */
  final class ofLong(override val repr: Array[Long]) extends AnyVal with ArrayOps[Long] with ArrayLike[Long, Array[Long]] {

    override protected[this] def thisCollection: WrappedArray[Long] = new WrappedArray.ofLong(repr)
    override protected[this] def toCollection(repr: Array[Long]): WrappedArray[Long] = new WrappedArray.ofLong(repr)
    override protected[this] def newBuilder = new ArrayBuilder.ofLong

    def length: Int = repr.length
    def apply(index: Int): Long = repr(index)
    def update(index: Int, elem: Long) { repr(index) = elem }
  }

  /** 包含`Float`的数组的`ArrayOps`的子类。 */
  final class ofFloat(override val repr: Array[Float]) extends AnyVal with ArrayOps[Float] with ArrayLike[Float, Array[Float]] {

    override protected[this] def thisCollection: WrappedArray[Float] = new WrappedArray.ofFloat(repr)
    override protected[this] def toCollection(repr: Array[Float]): WrappedArray[Float] = new WrappedArray.ofFloat(repr)
    override protected[this] def newBuilder = new ArrayBuilder.ofFloat

    def length: Int = repr.length
    def apply(index: Int): Float = repr(index)
    def update(index: Int, elem: Float) { repr(index) = elem }
  }

  /** 包含`Double`的数组的`ArrayOps`的子类。 */
  final class ofDouble(override val repr: Array[Double]) extends AnyVal with ArrayOps[Double] with ArrayLike[Double, Array[Double]] {

    override protected[this] def thisCollection: WrappedArray[Double] = new WrappedArray.ofDouble(repr)
    override protected[this] def toCollection(repr: Array[Double]): WrappedArray[Double] = new WrappedArray.ofDouble(repr)
    override protected[this] def newBuilder = new ArrayBuilder.ofDouble

    def length: Int = repr.length
    def apply(index: Int): Double = repr(index)
    def update(index: Int, elem: Double) { repr(index) = elem }
  }

  /** 包含`Boolean`的数组的`ArrayOps`的子类。 */
  final class ofBoolean(override val repr: Array[Boolean]) extends AnyVal with ArrayOps[Boolean] with ArrayLike[Boolean, Array[Boolean]] {

    override protected[this] def thisCollection: WrappedArray[Boolean] = new WrappedArray.ofBoolean(repr)
    override protected[this] def toCollection(repr: Array[Boolean]): WrappedArray[Boolean] = new WrappedArray.ofBoolean(repr)
    override protected[this] def newBuilder = new ArrayBuilder.ofBoolean

    def length: Int = repr.length
    def apply(index: Int): Boolean = repr(index)
    def update(index: Int, elem: Boolean) { repr(index) = elem }
  }

  /** 包含`Unit`类型的数组的`ArrayOps`的子类。 */
  final class ofUnit(override val repr: Array[Unit]) extends AnyVal with ArrayOps[Unit] with ArrayLike[Unit, Array[Unit]] {

    override protected[this] def thisCollection: WrappedArray[Unit] = new WrappedArray.ofUnit(repr)
    override protected[this] def toCollection(repr: Array[Unit]): WrappedArray[Unit] = new WrappedArray.ofUnit(repr)
    override protected[this] def newBuilder = new ArrayBuilder.ofUnit

    def length: Int = repr.length
    def apply(index: Int): Unit = repr(index)
    def update(index: Int, elem: Unit) { repr(index) = elem }
  }
}
override protected[this] def thisCollection: WrappedArray[Unit] = new WrappedArray.ofUnit(repr)
    override protected[this] def toCollection(repr: Array[Unit]): WrappedArray[Unit] = new WrappedArray.ofUnit(repr)
    override protected[this] def newBuilder = new ArrayBuilder.ofUnit

    def length: Int = repr.length
    def apply(index: Int): Unit = repr(index)
    def update(index: Int, elem: Unit) { repr(index) = elem }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BigDataMLApplication

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值