0

我得到了List[String],我需要分组。对于每个块,我需要运行一个返回List[String]结果的查询 (JDBC)。

我想要达到的是:

  • 来自不同块的所有结果连接在一个平面列表中
  • 最终的平面列表是一个非严格的集合(以免将整个 ResultSet 加载到内存中)

这就是我所做的:

Stream从 a产生a ResultSet,给定 a List[String](这是块):

def resultOfChunk(chunk: List[String])(statement: Statement): Stream[String] = {
 //..
  val resultSet = statement.executeQuery(query)
  new Iterator[String] {
    def hasNext = resultSet.next()
    def next() = resultSet.getString(1)
  }.toStream
}

制作最终名单:

val initialList: List[String] = //.. 

val connection = //..
val statement = connection.createStatement
val streams = for {
  chunk <- initialList.grouped(10)
  stream = resultOfChunk(chunk)(statement)
} yield stream

val finalList = streams.flatten

statement.close()
connection.close()

(变量名称旨在证明这个概念)。

它似乎有效,但我有点紧张:

  1. 产生一个Iterator[Stream]理解。这是人们做的事情吗?
  2. 展平说Iterator[Stream] (我可以假设他们在展平期间没有得到评估吗?)。
  3. 关闭连接和语句后,有什么方法可以使用最终列表?
    比如说,如果我需要进行持续很长时间的操作并且不想在此期间保持连接打开,我有什么选择?
  4. 这段代码是否真的阻止了一次将整个 DB ResultSet 加载到内存中(这是我的实际目标)?
4

1 回答 1

1

我会一一回复:

  1. 当然,为什么不呢。为了便于阅读,您可能需要考虑直接在理解中进行展平。

    val finalList = for {
      chunk  <- initialList.grouped(10)
      result <- resultOfChunk(chunk)(statement)
    } yield result
    
  2. 见上面的扁平化。是的,您可以假设他们不会被评估。

  3. Iterator不能重复使用(假设给initialList.grouped(10)你一个迭代器)。但是您可以使用 aStream而不是 anIterator然后,是的,您可以,但是:
    • 必须确保在关闭连接之前对其进行全面评估
    • 会将所有数据存储在内存中
  4. 是的,它确实

根据我所看到的,我向您推荐以下内容:

val finalList = for {
  chunk  <- initialList.grouped(10).toStream
  result <- resultOfChunk(chunk)(statement)
} yield result

这将为您提供Stream[String]根据需要评估的值(按顺序访问时)。完全评估后,您可以关闭数据库连接并继续使用它。

于 2013-05-03T16:20:53.210 回答