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)
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,如果我定义了这样的方法:
def genSet:Set[Int] = {
TreeSet(5, 4, 3, 2, 1)
}
Run Code Online (Sandbox Code Playgroud)
当我想使用for循环时
for (i <- genSet; x = i + 1) {
println(x)
}
Run Code Online (Sandbox Code Playgroud)
结果是未排序的,如何在不更改genSet返回类型的情况下修复此行为.如果我像下面一样使用循环,它会很好,但我希望保持上面的代码风格.
for (i <- genSet) {
val x = i + 1
println(x)
}
Run Code Online (Sandbox Code Playgroud)
Ken*_*oom 12
map版本结束了未分类除了返回选择适当返回类型的类型之外,该map方法(使用我们将调用的函数调用func)采用一个隐式CanBuildFrom参数,该参数考虑了map被调用的集合的func类型.这用于制作Map.map[Int]或BitSet.map[String]做正确的事情(返回通用列表)同时Map.map[(String,Int)]或者BitSet.map[Int]也做正确的事情(分别返回a Map和a BitSet).
该CanBuildFrom是在编译时选择,所以它必须根据选择静态类型的调用集合map上(在编译时,编译器知道的类型).静态类型set是TreeSet,但静态类型diffset是Set.两者的动态类型(在运行时)是TreeSet.
当你打电话map给set(a TreeSet)时,编译器选择immutable.this.SortedSet.canBuildFrom[Int](math.this.Ordering.Int)为CanBuildFrom.
当你打电话map给diffset(a Set)时,编译器选择immutable.this.Set.canBuildFrom[Int]为CanBuildFrom.
for版本结束了未分类循环
for (i <- genSet; x = i + 1) {
println(x)
}
Run Code Online (Sandbox Code Playgroud)
desugars into
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)
}))
Run Code Online (Sandbox Code Playgroud)
desugared版本包括一个map功能,将使用未分类CanBuildFrom,如上所述.
另一方面,循环
for (i <- genSet) {
val x = i + 1
println(x)
}
Run Code Online (Sandbox Code Playgroud)
desugars into
genSet.foreach(((i) => {
val x = i.$plus(1);
println(x)
}))
Run Code Online (Sandbox Code Playgroud)
CanBuildFrom因为没有返回新的集合,所以根本不使用a .