我有一个Option[mutable.Traversable[Field]]类型的变量underlying
我想在我的类中做的所有事情就是提供一个方法,以如下方式将其作为序列返回:
def toSeq: scala.collection.mutable.Seq[Field] = {
for {
f <- underlying.get
} yield f
}这会失败,因为它会抱怨mutable.traversable不符合mutable.seq。它所做的就是产生Field类型的东西--在我看来,这应该是可行的?
一种可能的解决方案是:
def toSeq: Seq[Field] = {
underlying match {
case Some(x) => x.toSeq
case None =>
}
}虽然我不知道当x.toSeq被调用时实际发生了什么,我想这里使用了更多的内存来完成这一任务。
如果您能给我一个解释或建议,我们将不胜感激。
发布于 2017-01-06 20:45:07
我不明白为什么你会说“我想这里使用的内存比实际需要的要多”。在执行x.toSeq时,Scala不会复制您的Field值,它只是创建一个新的Seq,它将具有指向underlying所指向的相同Field值的指针。由于这种新结构正是您想要的,因此无法避免与额外指针相关的额外内存(但额外内存的数量应该很小)。有关更深入的讨论,请参阅persistent data structures上的维基。
关于您可能的解决方案,可以稍微修改一下,以获得您期望的结果:
def toSeq : Seq[Field] =
underlying
.map(_.toSeq)
.getOrElse(Seq.empty[Field])如果underlying是一个比使用get的原始尝试更安全的None,则此解决方案将返回一个空的Seq。我之所以说它“更安全”,是因为如果选项是一个NoSuchElementException,get就会抛出一个None,而我的toSeq总是会返回一个有效的值。
函数式方法
作为附注:当我第一次开始使用scala编程时,我会编写许多如下形式的函数:
def formatSeq(seq : Seq[String]) : Seq[String] =
seq map (_.toUpperCase)这不太有用,因为你期望的是一个特定的集合类型,例如formatSeq不能在Future上工作。
我发现更好的方法是这样写:
def formatStr(str : String) = str.toUpperCase或者我更喜欢的编码风格:
val formatStr = (_ : String).toUpperCase然后你的函数的用户可以以任何他们想要的方式应用formatStr,你不必担心所有的集合类型转换:
val fut : Future[String] = ???
val formatFut = fut map formatStr
val opt : Option[String] = ???
val formatOpt = opt map formatStrhttps://stackoverflow.com/questions/41503388
复制相似问题