【问题标题】:Iterator.continually: special proccessing for the first elementIterator.continually:对第一个元素进行特殊处理
【发布时间】:2020-08-30 09:24:45
【问题描述】:

我有一个基于重复函数调用的Iterator

anObject.synchronized {
    Iterator.continually { 
        anObject.wait()      // skip this call for the 1st iteration
        Try(anObject.foo()) 
    }.dropWhile(_.isFailure).next()
    anObject.notifyAll()
}

我想在不调用anObject.wait() 的情况下进行第一次迭代。当然,我可以制作如下内容:

anObject.synchronized {
    if (Try(anObject.foo()).isFailure) {
        Iterator.continually { 
            anObject.wait()
            Try(anObject.foo()) 
        }.dropWhile(_.isFailure).next()
    }
    anObject.notifyAll()
}

是否有更优雅或标准的方法来获得相同的目的(在第一次迭代时跳过函数调用)

PS 当需要打印带有分隔符的列表时会出现类似的任务:

scala> List("a", "b", "c").mkString(", ")
res1: String = a, b, c

所以,我希望我的问题也有一些方法

【问题讨论】:

  • 我现在无法添加答案,但是 Iterator.single(f) ++ Iterator.continually(g)
  • @LuisMiguelMejíaSuárez - 谢谢。我想,这是一个有趣的解决方案。我想投票赞成答案:)
  • 我刚刚意识到这是行不通的,因为single 是急切的,这可能不是你想要的。顺便说一句,既然你在这里有并发和多线程,让我告诉你 Iterator 会有问题。我建议您切换到像 AkkaStreamsfs2monix observablesZio ZStreams 这样的强大流解决方案。
  • @LuisMiguelMejíaSuárez - 谢谢。那么这个问题interests我也是

标签: multithreading scala iterator synchronized


【解决方案1】:

也许创建一个新的迭代器来检查第一个元素

def continually[A](firstElem: => A)(elem: => A): Iterator[A] = new AbstractIterator[A] {
    var isFirst = true
    def hasNext = true
    def next(): A = if (isFirst) { isFirst = false; firstElem } else elem
  }

continually("a")("b").take(3).foreach(print)
// abb

【讨论】:

    【解决方案2】:

    您可以将 .continually 更改为 .tabulate,只要 2,147,483,647 不会对迭代次数造成有意义的限制。

    anObject.synchronized {
        Iterator.tabulate { n => 
            if (n != 0) anObject.wait()  // skip 1st iteration
            Try(anObject.foo()) 
        }.dropWhile(_.isFailure).next()
        anObject.notifyAll()
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-19
      • 1970-01-01
      相关资源
      最近更新 更多