5

我正在查看toArrayfor hashmaps 的定义:

http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.HashMap

它有

toArray: Array[A]
def toArray[B >: (A, B)](implicit arg0: ClassTag[B]): Array[B]

我不太明白这一点 - 第一部分说你得到了一个 Array[A],但第二部分说你得到了 Array[B]?这些都不是我所期望的 - Array[(A,B)]

当我自己检查时:

scala> val x = scala.collection.mutable.HashMap[String, Int]()
x: scala.collection.mutable.HashMap[String,Int] = Map()

scala> x.put("8", 7)
res0: Option[Int] = None

scala> x foreach println
(8,7)

scala> x.toArray
res2: Array[(String, Int)] = Array((8,7))

为什么不像 toList?

toList: scala.List[(A, B)]
4

3 回答 3

5

scaladoc 有各种微妙的错误。这里的问题是您看到的是方法签名的“简化”版本(旨在传达签名的基本部分并隐藏诸如CanBuildFromin map/flatMap方法之类的东西,这实际上是一个实现细节)。简化在这里有点不对劲,似乎没有多大意义。如果您单击“完整签名”链接,您会看到真正的签名如下所示:

def toArray[B >: (A, B)](implicit arg0: ClassTag[B]): Array[B]

事实上这仍然是错误的,因为我们当然不能有一个 B >: (A, B) 的类型 B。它应该更像:

def toArray[C >: (A, B)](implicit arg0: ClassTag[C]): Array[C]

问题是实际上有两个B:第一个来自HashMap类声明本身(HashMap[A, +B]),而另一个来自toArray其基类中定义 的方法TraversableOncedef toArray[B >: A](implicit arg0: ClassTag[B]): Array[B])。只是碰巧 scaladoc 生成器未能删除两个实例B

于 2013-06-24T14:41:29.433 回答
2

您在 Scaladoc 中看到的 API toArray

def toArray[B >: (A, B)](implicit arg0: ClassTag[B]): Array[B]

相当于:

def toArray[C >: (A, B)](implicit arg0: ClassTag[C]): Array[C]

类型变量的选择B确实是不幸的(甚至可能是一个 Scaladoc 错误,我不确定你是否被允许这样写)。

(A,B) 这基本上意味着您将获得aClassTag可用的最特定超类型的数组。是ClassTag创建Array.

这基本上意味着,如果在编译时,Map您正在转换的运行时类型是完全已知的,您将获得一个Array[(A,B)]. 但是,如果您在Map某处进行了向上转换,则结果的运行时类型Array将取决于向上转换的类型,而不是运行时类型。这toList与 JVM 对如何创建本机数组的限制不同的行为。

于 2013-06-24T14:38:25.897 回答
1

Scaladoc 是错误的,因为它继承toArrayTraversableOnce,其中集合的类型A和返回值是BArray[A]遗留的东西是从TraversableOnce哪里遍历的(在这种情况下,实际上是对于and的不同定义);尽管它以长格式正确填写,但它仍然用作新的返回变量,而不是像.ATraversableOnce(A,B)AB(A,B)BC

有点混乱!它实际上应该读

def toArray[C >: (A,B)](...[C]): Array[C]

简短的形式应该是

toArray: Array[(A,B)]

就像你期望的那样。

于 2013-06-24T14:40:36.933 回答