声明类型不同时的不同行为(Set 与 TreeSet)
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循环,那就没问题了,但我希望保留上面的代码风格。
for (i <- genSet) {
val x = i + 1
println(x)
}
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)
}
My question is if I defined a method like this:
def genSet:Set[Int] = {
TreeSet(5, 4, 3, 2, 1)
}
and when i want to use a for loop with it
for (i <- genSet; x = i + 1) {
println(x)
}
the result is unsorted, how to fix this behavior without change the genSet
's return type. if I use for loop like below, it will be fine, but I hope to keep the above code style.
for (i <- genSet) {
val x = i + 1
println(x)
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
为什么
map
版本最终未排序map
方法(使用我们将调用func
的函数调用)采用隐式CanBuildFrom
参数,除了考虑func
返回的类型以选择适当的返回类型之外,还考虑调用map
的集合类型。这用于使Map.map[Int]
或BitSet.map[String]
做正确的事情(返回通用列表),而Map.map[ (String,Int)]
或BitSet.map[Int]
也做正确的事情(返回一个Map
和一个BitSet
) 分别。CanBuildFrom
是在编译时选择的,因此必须根据您调用map
的集合的静态类型(类型编译器在编译时就知道)。set
的静态类型是TreeSet
,但diffset
的静态类型是Set
。两者(运行时)的动态类型都是TreeSet
。当您在
set
(TreeSet
)上调用map
时,编译器会选择immutable.this.SortedSet.canBuildFrom[Int](math .this.Ordering.Int)
作为CanBuildFrom
。当您在
diffset
(Set
)上调用map
时,编译器会选择immutable.this.Set.canBuildFrom[Int] 作为
CanBuildFrom
。为什么
for
版本最终未排序循环脱
糖为
脱糖版本包含一个
map
函数,该函数将使用未排序的CanBuildFrom
,正如我上面所解释的。另一方面,循环
脱糖到
Which 根本不使用
CanBuildFrom
,因为没有返回新的集合。Why the
map
version winds up unsortedThe
map
method (called with a function that we'll callfunc
) takes an implicitCanBuildFrom
parameter that takes into account the type of the collection thatmap
is being called on, in addition to the type thatfunc
returns to choose an appropriate return type. This is used to makeMap.map[Int]
orBitSet.map[String]
do the right thing (return general purpose lists) whileMap.map[(String,Int)]
orBitSet.map[Int]
also do the right thing (return aMap
and aBitSet
) respectively.The
CanBuildFrom
is chosen at compile time, so it must be chosen based on the static type of the set that you callmap
on (the type the compiler knows about at compile time). The static type ofset
isTreeSet
, but the static type ofdiffset
isSet
. The dynamic type of both (at runtime) isTreeSet
.When you call
map
onset
(aTreeSet
), the compiler choosesimmutable.this.SortedSet.canBuildFrom[Int](math.this.Ordering.Int)
as theCanBuildFrom
.When you call
map
ondiffset
(aSet
), the compiler choosesimmutable.this.Set.canBuildFrom[Int]
as theCanBuildFrom
.Why the
for
version winds up unsortedThe loop
desugars into
The desugared version includes a
map
function which will use the unsortedCanBuildFrom
as I explained above.On the other hand, the loop
desugars into
Which doesn't use a
CanBuildFrom
at all, since no new collection is being returned.Set
不保证顺序。即使底层类是TreeSet
,如果预期结果是Set
,您也会在第一次转换时失去顺序。如果您想要排序,请不要使用
Set
。我建议使用SortedSet
。Set
does not guarantee ordering. Even if the underlying class is aTreeSet
, if the expected result is aSet
you'll loose the ordering in the first transformation you do.If you want ordering, do not use
Set
. I suggest, say,SortedSet
.更改 genSet 的 sig 以返回 SortedSet
这可能是某种错误。我本来希望你的代码也能工作。
我认为
map
是罪魁祸首。这会导致相同的行为:并且
for(i <- genSet; x = i + 1)
等于for(x <- genSet.map({i => i + 1}))
Change the sig of
genSet
to return aSortedSet
This is probably some sort of bug. I would have expected your code to work too.
I think
map
is the culprit. This results in the same behavior:And
for(i <- genSet; x = i + 1)
equates tofor(x <- genSet.map({i => i + 1}))
你可以这样做:
虽然,这是一种技巧,当你几个月后查看它时,你可能想知道为什么添加
.view
...You can do:
Although, it's the type of trick that when you look at it after a few months, you may wonder why you added
.view
...