【问题标题】:Scala lazy elements in iterator迭代器中的 Scala 惰性元素
【发布时间】:2013-01-02 01:16:03
【问题描述】:

有人知道如何在 scala 中创建惰性迭代器吗?

例如,我想通过实例化每个元素进行迭代。通过后,我希望实例死亡/从内存中删除。

如果我像这样声明一个迭代器:

val xs = Iterator(
 (0 to 10000).toArray,
 (0 to 10).toArray,
 (0 to 10000000000).toArray)

它在声明 xs 时创建数组。可以这样证明:

def f(name: String) = {
  val x =  (0 to 10000).toArray
  println("f: " + name) 
  x
}

val xs = Iterator(f("1"),f("2"),f("3"))

哪个打印:

scala> val xs = Iterator(f("1"),f("2"),f("3"))
f: 1
f: 2
f: 3
xs: Iterator[Array[Int]] = non-empty iterator

有人有什么想法吗?

流不适合,因为元素保留在内存中。

注意:我以数组为例,但我希望它适用于任何类型。

【问题讨论】:

  • 这个 hack 似乎按我的意愿执行: val it = List(() => g("1"), () => g("2"), () => g( "3")).toIterator.map(_())

标签: scala


【解决方案1】:

Scala 集合有一个 view 方法,它产生一个惰性的集合等价物。所以不要使用(0 to 10000).toArray,而是使用(0 to 10000).view。这样,内存中就不会创建数组。另请参阅https://stackoverflow.com/a/6996166/90874https://stackoverflow.com/a/4799832/90874https://stackoverflow.com/a/4511365/90874 等。

【讨论】:

  • 如果我将它们放在一个列表中,它们将在列表期间保留在内存中。当我越过那个元素时,我只希望它们在内存中。
  • 我以数组为例,但我希望它适用于任何类型。
  • @SomeoneElse:被放入列表并不意味着没有资格被垃圾收集器回收。例如,如果您构建一个包含 10 个项目和 drop 前 5 个项目的列表,那么这 5 个 cons 单元格将是垃圾,内容值也将是垃圾(假设没有其他任何东西保留对这些列表单元格或其包含的值的引用) .
【解决方案2】:

使用Iterator 接受名称调用参数的工厂方法之一。

对于您的第一个示例,您可以执行以下操作:

val xs1 = Iterator.fill(3)((0 to 10000).toArray)
val xs2 = Iterator.tabulate(3)(_ => (0 to 10000).toArray)
val xs3 = Iterator.continually((0 to 10000).toArray).take(3)

只有在需要时才会分配数组。

如果您需要为每个元素使用不同的表达式,您可以创建单独的迭代器并将它们连接起来:

val iter = Iterator.fill(1)(f("1")) ++ 
           Iterator.fill(1)(f("2")) ++ 
           Iterator.fill(1)(f("3"))

【讨论】:

    猜你喜欢
    • 2012-09-20
    • 1970-01-01
    • 2015-11-12
    • 2011-01-16
    • 1970-01-01
    • 2019-06-20
    • 1970-01-01
    • 1970-01-01
    • 2017-01-08
    相关资源
    最近更新 更多