Scala:索引序列的易变性以及转换为易变序列和返回序列时会发生什么

Scala:索引序列的易变性以及转换为易变序列和返回序列时会发生什么,scala,immutability,toarray,mutability,Scala,Immutability,Toarray,Mutability,我最近多次遇到这种情况: 类具有不可变(索引?)序列成员 factory成员方法创建一个新实例,其序列经过了一些修改 做这件事的有效方法是什么 class A( xs: IndexedSeq[Int] ) { def another: A = { val ys = xs.toArray.clone() // !!! ys(7) = 13 new A(ys) } } 我会.toArray,这样我就可以就地修改这个序列和.clon

我最近多次遇到这种情况:

  • 类具有不可变(索引?)序列成员
  • factory成员方法创建一个新实例,其序列经过了一些修改
  • 做这件事的有效方法是什么

    class A( xs: IndexedSeq[Int] ) {
        def another: A = {
            val ys = xs.toArray.clone()   // !!!
            ys(7) = 13
            new A(ys)
        }
    }
    
    我会.toArray,这样我就可以就地修改这个序列和.clone,因为我担心如果原始的xs已经是一个数组,toArray将只返回这个值,我将修改对象(意味着不可变)的值。然而,如果xs不是数组,那么这显然会产生两个副本,我真的希望避免这种情况。显然,我可以只检查它的类型,但这似乎非常不雅观,我不太确定是否需要检查其他可以包装数组的可变序列。你怎么办

    scala> val xs: Seq[Int] = Array(1, 2, 3)
    ss: Seq[Int] = WrappedArray(1, 2, 3)
    
    scala> val ys = xs.toArray
    ys: Array[Int] = Array(1, 2, 3)
    
    scala> ys(1) = 22
    
    scala> ys
    res1: Array[Int] = Array(1, 22, 3)
    
    scala> xs
    res2: Seq[Int] = WrappedArray(1, 22, 3)
    

    如果你真的不需要可变性,那么最好的方法就是要求一个不可变的序列;这样,您就不必担心更改数据是否会产生副作用

    class A(xs: collection.immutable.IndexedSeq[Int]) {
      def another: A = {
        val ys = xs.updated(7, 13)
        new A(ys)
      }
    }
    

    效率高吗?我怀疑平均而言,我将进行O(n)更新(xs.size/2)。哎呀,类型别名有点分裂:
    Predef.Map
    Predef.Set
    是不可变的,而
    scala.Seq
    scala.IndexedSeq
    是通用的,我想这是为了允许与数组交互。默认工厂是不可变的,即使是
    Seq(1,2,3)
    (给出
    列表)和
    IndexedSeq(1,2,3)
    (给出
    向量
    )。所以这有点混乱。