我有一个使用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)
有更好的方法吗?
答案 0 :(得分:5)
Scala的Set
层次结构有点奇怪,但BitSet
将Set[Int]
作为超类型,因此您只需将BitSet
传递给需要Set[Int]
等的方法
这似乎不是这种情况,因为您默认获得的Set
为immutable.Set
(在scala.collection
下),而您正在使用的库可能正在使用BitSet
直接位于scala.collection
下,而不是immutable.BitSet
。在您的示例代码中并非如此,其中所有内容都在immutable
中,但我不确定它是多么简化。
如果您有幸使用immutable
包Set
和BitSet
版本,BitSet
到Set
方向是微不足道的:
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)
但是BitSet
参数不是在collection.breakOut
之前构造一个中间集(和序列),而是告诉编译器使用CanBuildFrom
类型类的实例来执行映射。直接构造BitSet
。以这种方式明确传递CanBuildFrom
实例不仅适用于map
,它也适用于flatMap
,scanLeft
,++
和其他允许您更改元素类型的集合操作。
答案 1 :(得分:0)
思考面向对象:BitSet
是一个Set[Int]
,你不需要做任何事情来将一个转换为另一个:
import scala.collection._
val set: Set[Int] = BitSet(1,2,3)
走另一条路更难,并且需要线性时间:
val bs: BitSet = BitSet(set.toStream:_*)
但是每当你发现自己需要这种" upconverting"时,99%的时间都是设计糟糕的标志,应该改进以消除需求:特定的实现细节{ {1}}应该只对最初创建它的代码有用,下游代码通常应该与实现无关。