var set = TreeSet(5,4,3,2,1)
println(set)
val diffSet: TreeSet[Int] = set
// if I change above code to val diffSet: Set[Int] = set
// the result is unsorted set.
for (i <- diffSet; x = i) {
println(i)
}
println("-" * 20)
// the above code translates to below and print the same result
val temp = diffSet.map(i => (i, i))
for ((i, x) <- temp) {
println(i)
}
我的问题是我是否定义了这样的方法:
def genSet:Set[Int] = {
TreeSet(5, 4, 3, 2, 1)
}
当我想使用for循环时
for (i <- genSet; x = i + 1) {
println(x)
}
结果未排序,如何修改此行为而不更改genSet
的返回类型。如果我像下面一样使用循环,它会没问题,但我希望保持上面的代码风格。
for (i <- genSet) {
val x = i + 1
println(x)
}
答案 0 :(得分:12)
map
版本结束了未排序的 map
方法(使用我们称之为func
的函数调用)采用隐式CanBuildFrom
参数,该参数考虑了map
的集合类型正在调用,除了func
返回以选择适当的返回类型的类型。这用于使Map.map[Int]
或BitSet.map[String]
做正确的事情(返回通用列表),而Map.map[(String,Int)]
或BitSet.map[Int]
也做正确的事情(返回{{1}分别是Map
。
在编译时选择BitSet
,因此必须根据您调用CanBuildFrom
的集合的 static 类型来选择它(编译器知道的类型)约在编译时)。 map
的静态类型为set
,但TreeSet
的静态类型为diffset
。两者的动态类型(在运行时)是Set
。
当您在TreeSet
(map
)上致电set
时,编制者会选择TreeSet
作为immutable.this.SortedSet.canBuildFrom[Int](math.this.Ordering.Int)
。
当您在CanBuildFrom
(map
)上致电diffset
时,编制者会选择Set
作为immutable.this.Set.canBuildFrom[Int]
。
CanBuildFrom
版本结束了未排序的循环
for
desugars into
for (i <- genSet; x = i + 1) {
println(x)
}
desugared版本包含一个genSet.map(((i) => {
val x = i.$plus(1);
scala.Tuple2(i, x)
})).foreach(((x$1) => x$1: @scala.unchecked match {
case scala.Tuple2((i @ _), (x @ _)) => println(x)
}))
函数,它将使用我上面解释的未排序的map
。
另一方面,循环
CanBuildFrom
desugars into
for (i <- genSet) {
val x = i + 1
println(x)
}
根本不使用genSet.foreach(((i) => {
val x = i.$plus(1);
println(x)
}))
,因为没有返回新的集合。
答案 1 :(得分:6)
Set
不保证订购。即使基础类是TreeSet
,如果预期结果是Set
,您将在第一次转换中失去排序。
如果您想要订购,请不要使用Set
。我建议说,SortedSet
。
答案 2 :(得分:2)
更改genSet
的签名以返回SortedSet
def genSet:SortedSet[Int] = {
TreeSet(5, 4, 3, 2, 1)
}
这可能是某种错误。我本来希望你的代码能够运行。
我认为map
是罪魁祸首。这会导致相同的行为:
for (i <- genSet.map(_ + 1)) { println(i) }
for(i <- genSet; x = i + 1)
等同于for(x <- genSet.map({i => i + 1}))
答案 3 :(得分:0)
你可以这样做:
scala> for (i <-genSet.view; x = i + 1) println(x)
2
3
4
5
6
虽然,这是一种技巧,当你在几个月后看它时,你可能想知道为什么你添加了.view
......