Scala为inits
定义了List
方法,该方法执行以下操作:
List(1, 2, 3).inits.toList // List(List(1, 2, 3), List(1, 2), List(1), List())
以这种方式实现:
def inits: Iterator[Repr] = iterateUntilEmpty(_.init)
private def iterateUntilEmpty(f: Traversable[A @uV] => Traversable[A @uV]): Iterator[Repr] = {
val it = Iterator.iterate(thisCollection)(f) takeWhile (x => !x.isEmpty)
it ++ Iterator(Nil) map (x => (newBuilder ++= x).result)
}
我掀起了一个不太通用的版本(只是为了玩):
val L = List(1,2,3)
val it = Iterator.iterate(L)(_.init) takeWhile (x => !x.isEmpty)
it ++ Iterator(Nil) map (x => (new ListBuffer ++= x).result) toList
// List(List(1, 2, 3), List(1, 2), List(1), List())
但是在我看来,我们可以不用ListBuffer
部分:
val L = List(1,2,3)
val it = Iterator.iterate(L)(_.init) takeWhile (x => !x.isEmpty)
it ++ Iterator(Nil) toList
// List(List(1, 2, 3), List(1, 2), List(1), List())
结果似乎是一样的。
那么为什么库实现使用newBuilder
?
它对性能有何影响?
答案 0 :(得分:1)
希望Rex Kerr @ rex-kerr能够启动某种长期工作并检查SO的问题,但在此之前,您已经问过为什么没有列出专门的{{1} }。
我认为两个答案是专门针对每个具体的集合都是一个维护问题,并且重写该方法会与JVM的策略竞争以进行编译。
我想我在消息来源中读到,在性能受到影响之前,JVM将容忍两次这样的调度以覆盖。我不是专家,但直觉是假设一种方法实际上是最终的更有效。
但等一下,您的TraversableLike.inits
与.toList
不一样。
你的问题减少了,为什么不完全为List留下建设者,因为你从迭代器获得了列表。
好吧,也许它不适用于其他类型:
.map(_.toList)