类型参数化和奇怪的强制类型转换异常



我有以下代码,在满足谓词p的任何元素之前将数组拆分为数组的数组。它的类型检查:

def splitBefore[T](a: Array[T], p: (T) => Boolean)
      (implicit tct: ClassTag[T]): Array[Array[T]] =
  a.foldLeft(Array[Array[T]](Array.empty[T])) {
(acc: Array[Array[T]], s: T) => if (p(s))
  acc :+ Array(s)
else
  acc.init :+ (acc.last :+ s)
}

当我用非空a调用它时,它工作得很好:

scala> splitBefore(Array("a", "BC", "d"), (s: String) => s.size > 1)
res1: Array[Array[String]] = Array(Array(a), Array(BC, d))

但是当我用一个空数组调用它时,我得到一个ClassCastException:

scala> splitBefore(Array.empty[String], (s: String) => s.size > 1)
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [[Ljava.lang.String;
  ... 33 elided
当我手工内联调用时,没有类型参数化,它工作得很好:
scala> Array().foldLeft(Array(Array.empty[String])) {
     |   (acc: Array[Array[String]], s: String) => if (s.size > 1)
     |     acc :+ Array(s)
     |   else
     |     acc.init :+ (acc.last :+ s)
     | }
res1: Array[Array[String]] = Array(Array())

你知道这是怎么回事吗?我使用的是Scala 2.11.7.

看起来像实例化嵌套数组会导致错误——即使在这样一个小示例上也会崩溃:

def instantiate[A](ununsed_arg: Array[T])(implicit tag: ClassTag[A]) =
  Array[Array[A]](Array.empty[A])

作为一个快速的解决方案,你可以使用ArrayBuilder来创建一个数组:

def instantiate[T](a: Array[T])(implicit ctc: ClassTag[T]) = {
  val builder = ArrayBuilder.make[Array[T]]
  builder += Array.empty[T]
  builder.result
}

还请注意,您的代码片段直接将元素追加到数组中,这是一个坏主意,因为它必须创建一个多一个槽的新数组并复制一个元素。看起来您应该使用ArrayBuilderArrayBuffer来进行处理或从列表中构建新的数据结构并在最后将它们转换为Arrays

最新更新