从 Scala 中的 mutable.traversable 类型生成 mutable.seq

Yield mutable.seq from mutable.traversable type in Scala

提问人:Chris Beck 提问时间:1/6/2017 更新时间:1/8/2017 访问量:64

问:

我有一个类型的变量underlyingOption[mutable.Traversable[Field]]

我想在我的课堂上做的就是提供一种方法,以以下方式将其作为 Sequence 返回:

def toSeq: scala.collection.mutable.Seq[Field] = {
  for {
    f <- underlying.get
  } yield f
}

这失败了,因为它抱怨不符合 .它所做的只是产生字段类型的东西 - 在我看来这应该有效吗?mutable.traversablemutable.seq

一个可能的解决方案是:

def toSeq: Seq[Field] = {
  underlying match {
    case Some(x) => x.toSeq
    case None =>
  }
}

虽然我不知道调用x.toSeq时实际发生了什么,但我想这里使用了更多的内存来完成此操作。

如能提供解释或建议,将不胜感激。

斯卡拉 收集 屈服 可变 序列

评论


答:

1赞 Ramón J Romero y Vigil 1/6/2017 #1

我很困惑为什么你说“我想这里使用的内存比实际需要完成的要多”。Scala 在执行时不会复制您的值,它只是创建一个新的值,该值将具有指向指向的相同值的指针。由于这个新结构正是你想要的,所以无法避免与额外指针相关的额外内存(但额外内存量应该很小)。有关更深入的讨论,请参阅有关持久性数据结构的 wiki。Fieldx.toSeqSeqFieldunderlying

关于您可能的解决方案,可以稍作修改以获得您期望的结果:

def toSeq : Seq[Field] = 
  underlying
    .map(_.toSeq)
    .getOrElse(Seq.empty[Field])

此解决方案将返回一个空的 if ,它比您使用 .我说它“更安全”,因为如果 Option 是 a,则会抛出 a,而 my 永远不会返回有效值。SequnderlyingNonegetgetNoSuchElementExceptionNonetoSeq

功能方法

顺便说一句:当我第一次开始用scala编程时,我会编写许多形式的函数:

def formatSeq(seq : Seq[String]) : Seq[String] = 
  seq map (_.toUpperCase)

这不太实用,因为您期望特定的集合类型,例如 在 .formatSeqFuture

我发现更好的方法是写:

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 formatStr

评论

0赞 Chris Beck 1/8/2017
非常有用。我在这里关心的纯粹是内存使用和性能
0赞 Ramón J Romero y Vigil 1/8/2017
@ChrisBeck 内存和时间的性能都将是 O(n),但正如我在响应中所说,内存使用量应该非常小,因为它只是指针。