4

在 Scala shell 中,我这样做了:

import java.util._
import scala.collection.JavaConversions._

val t: SortedMap[String,Int] = new TreeMap[String,Int] () // produces an empty java.util.SortedMap

t("a") = 1; t("b") = 2; t("A") = 3; t("0") = 4

t // prints: res35: java.util.SortedMap[String,Int] = {0=4, A=3, a=1, b=2}, as expected

t foreach println // also prints the (k,v) pairs in the same TreeMap sorted order

但是,以下语句并未按排序顺序打印对,而是按哈希桶顺序 (0,4) (b,2) (A,3) (a,1) 打印它们:

for ((k,v) <- t) printf("(%s,%d)%n", k, v)

在与 for 和 foreach 相关的其他答案中,似乎 for 理解应该转化为 foreach 的使用,如下所示:

“(p <- e) e0 的 for-comprehension 被转换为 e.foreach { case p => e0 }”

但这似乎不是这里发生的事情。

请注意,如果我从一个scala TreeMap 创建一个scala SortedMap ,那么 foreach 和 for 都按我预期的排序顺序生成 (k,v) 对。Java TreeMap 被转换为 scala 的方式似乎有所不同。

关于为什么会出现这种差异的任何意见或想法?

4

1 回答 1

7

嗯,p(k,v)不一样的东西。你的理解被翻译成这样:

t.filter{
  case (k, v) => true
  case _      => false
}.map {
  case (k, v) => printf("(%s,%d)$n")
}

一旦filter把它放在java集合上,它就变成了一个Scala集合,不再排序。

附带说明一下,在 Scala 2.10 上,上述内容不再适用,因为它在编译时检测到静态类型中没有不是 (k,v) 的元素,并且不生成过滤器。这里:

scala> for ((k,v) <- t) printf("(%s,%d)%n", k, v)
<console>:15: warning: dead code following this construct
              for ((k,v) <- t) printf("(%s,%d)%n", k, v)
                         ^
(0,4)
(A,3)
(a,1)
(b,2)

scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._

scala> reify{for ((k,v) <- t) printf("(%s,%d)%n", k, v)}
res4: reflect.runtime.universe.Expr[Unit] =
Expr[Unit](scala.collection.JavaConversions.mapAsScalaMap(t).foreach(((x$1) => x$1: @unchecked match {
  case scala.Tuple2((k @ _), (v @ _)) => scala.this.Predef.printf("(%s,%d)%n", k, v)
})))

PS:更JavaConverters喜欢JavaConversions.

于 2012-08-28T03:04:30.453 回答