在 Scala 中将 BitSet 设置为 Set[Int] 或反之亦然

BitSet to Set[Int] or vice versa in Scala

我有一个使用 BitSet 的库,我需要更改 Set[Int] 类型的数据才能使用该库。

我想到的是使用 .toSeq:_* 操作,但我不确定这是从 BitSet 转换为 Set[Int] 还是相反的有效方法。

scala> BitSet(Set(1,2,3).toSeq:_*)
res55: scala.collection.immutable.BitSet = BitSet(1, 2, 3)

scala> Set(BitSet(1,2,3).toSeq:_*)
res56: scala.collection.immutable.Set[Int] = Set(1, 2, 3)

有没有更好的方法?

Scala 的 Set 层次结构有点奇怪,但是 BitSet 的超类型是 Set[Int],所以你可以简单地传递一个 BitSet到一个需要 Set[Int] 等的方法

这似乎不是这种情况,因为默认情况下您获得的 Setimmutable.Set(在 scala.collection 下),而您使用的库可能是使用 scala.collection 下的 BitSet,而不是 immutable.BitSet。在您的示例代码中情况并非如此,所有内容都在 immutable 中,但我不确定它的简化程度。

如果您有幸使用 immutable 包的 SetBitSet 版本,则 BitSetSet 方向微不足道:

scala> import scala.collection.immutable.BitSet
import scala.collection.immutable.BitSet

scala> val bs = BitSet(0, 100, 200)
bs: scala.collection.immutable.BitSet = BitSet(0, 100, 200)

scala> def takesSet(s: Set[Int]): Int = s.size
takesSet: (s: Set[Int])Int

scala> takesSet(bs)
res0: Int = 3

如果你有 scala.collection.BitSet,只需使用 toSet:

scala> takesSet(scala.collection.BitSet(0, 100, 200).toSet)
res1: Int = 3

另外一个方向,你的版本没问题:

scala> val s = Set(1, 2, 3)
s: scala.collection.immutable.Set[Int] = Set(1, 2, 3)

scala> BitSet(s.toSeq: _*)
res2: scala.collection.immutable.BitSet = BitSet(1, 2, 3)

但同样值得注意的是,在许多情况下,您可以使用一些 CanBuildFrom 魔法来避免这种转换:

scala> val bs: BitSet = Set("1", "2", "3").map(_.toInt)(collection.breakOut)
bs: scala.collection.immutable.BitSet = BitSet(1, 2, 3)

这会产生与以下相同的结果:

scala> val bs: BitSet = BitSet(Set("1", "2", "3").map(_.toInt).toSeq: _*)
bs: scala.collection.immutable.BitSet = BitSet(1, 2, 3)

但是,collection.breakOut 参数告诉编译器使用 CanBuildFrom 类型的实例执行映射,而不是在 BitSet 之前构建中间集(和序列)class 将直接构造 BitSet。以这种方式显式传递 CanBuildFrom 实例不仅适用于 map,它也适用于 flatMapscanLeft++ 和其他允许您更改元素类型的集合操作。

认为面向对象:BitSet 一个Set[Int],你不需要做任何事情来将一个转换成另一个:

     import scala.collection._
     val set: Set[Int] = BitSet(1,2,3)

走另一条路更难,并且需要线性时间:

     val bs: BitSet = BitSet(set.toStream:_*)

但是当你发现自己需要这种 "upconverting" 时,99% 的情况下它是糟糕设计的标志,应该改进以消除这种需要:特定 [= 的实现细节14=] 应该只对最初创建它的代码有影响,下游代码通常应该与实现无关。