Scala Set 和洗牌的排序顺序
Sort Order for Scala Set and shuffling
scala
Welcome to Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_79).
Type in expressions to have them evaluated.
Type :help for more information.
scala> 300 to 1000 toSet
warning: there were 1 feature warning(s); re-run with -feature for details
res0: scala.collection.immutable.Set[Int] = Set(645, 892, 809, ...)
// 问题 # 1: 我预计再次 运行 时顺序会有所不同。它与 res0 的顺序相同。
所以我想,可能是 运行ge 太小而不能因不同的原因(系统熵等)而不同
scala> 300 to 1000 toSet
warning: there were 1 feature warning(s); re-run with -feature for details
res1: scala.collection.immutable.Set[Int] = Set(645, 892, 809, ...)
// 问题 # 2: 这太奇怪了。即使在洗牌之后,我也会看到相同的顺序。为什么?
scala> scala.util.Random.shuffle((300 to 1000).toSet)
res2: scala.collection.immutable.Set[Int] = Set(645, 892, 809, ...)
普通的Set
不保证任何顺序。这意味着它可以选择以它认为最有效或最方便的任何顺序存储数据。
它可能会选择以不同的顺序存储,具体取决于项目给它的顺序,也可能不会。它不作任何保证。
重要的是,如果它碰巧在一个版本的 scala 中这样做,根据这个特定的结果将是危险的,因为没有明确的保证。
所以,我不知道它为什么选择这个结果,但这个结果实际上是任意的,你不能依赖它。洗牌 Set
没有具体的价值,因为 Set
可以选择以它选择的任何顺序存储它们。
如果你需要在Set
中排序,那么选择TreeSet
或SortedSet
可以保证返回元素的顺序。
对 scala 中 Set
实现的内部结构有更多了解的其他人可能会提供有关实现细节的更详细的答案。
据我所知,默认的不可变 Set
是一个 HashSet
实现,因此,对于任何给定的 Set
值,无论它们的顺序如何,桶都不太可能改变插入。
scala 中的标准不可变 Set
实现为 哈希尝试 。它基本上是一棵树,使用添加到它的值的哈希码。这就是它如何有效地检测 Set
.
中已经存在的值
因为无论添加到集合中的顺序如何,添加值的散列码都是相同的,所以 Set
总是以相同的顺序是合理的。当然,需要注意的是,这个顺序既不是外部确定性的,也不是有保证的。因此,即使您喜欢 Set
的顺序,也不能保证它不会在编译器或 JVM
的任何版本中发生变化
scala
Welcome to Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_79).
Type in expressions to have them evaluated.
Type :help for more information.
scala> 300 to 1000 toSet
warning: there were 1 feature warning(s); re-run with -feature for details
res0: scala.collection.immutable.Set[Int] = Set(645, 892, 809, ...)
// 问题 # 1: 我预计再次 运行 时顺序会有所不同。它与 res0 的顺序相同。 所以我想,可能是 运行ge 太小而不能因不同的原因(系统熵等)而不同
scala> 300 to 1000 toSet
warning: there were 1 feature warning(s); re-run with -feature for details
res1: scala.collection.immutable.Set[Int] = Set(645, 892, 809, ...)
// 问题 # 2: 这太奇怪了。即使在洗牌之后,我也会看到相同的顺序。为什么?
scala> scala.util.Random.shuffle((300 to 1000).toSet)
res2: scala.collection.immutable.Set[Int] = Set(645, 892, 809, ...)
普通的Set
不保证任何顺序。这意味着它可以选择以它认为最有效或最方便的任何顺序存储数据。
它可能会选择以不同的顺序存储,具体取决于项目给它的顺序,也可能不会。它不作任何保证。
重要的是,如果它碰巧在一个版本的 scala 中这样做,根据这个特定的结果将是危险的,因为没有明确的保证。
所以,我不知道它为什么选择这个结果,但这个结果实际上是任意的,你不能依赖它。洗牌 Set
没有具体的价值,因为 Set
可以选择以它选择的任何顺序存储它们。
如果你需要在Set
中排序,那么选择TreeSet
或SortedSet
可以保证返回元素的顺序。
对 scala 中 Set
实现的内部结构有更多了解的其他人可能会提供有关实现细节的更详细的答案。
据我所知,默认的不可变 Set
是一个 HashSet
实现,因此,对于任何给定的 Set
值,无论它们的顺序如何,桶都不太可能改变插入。
scala 中的标准不可变 Set
实现为 哈希尝试 。它基本上是一棵树,使用添加到它的值的哈希码。这就是它如何有效地检测 Set
.
因为无论添加到集合中的顺序如何,添加值的散列码都是相同的,所以 Set
总是以相同的顺序是合理的。当然,需要注意的是,这个顺序既不是外部确定性的,也不是有保证的。因此,即使您喜欢 Set
的顺序,也不能保证它不会在编译器或 JVM