简短的回答:你不能比你所拥有的做得更好。在 Scala 的功能聪明的背后是看起来很像你的代码。另外,不要忘记 mutableMap
有一个toMap
返回 immutable 的方法Map
。
长答案:您正在寻找使用 Scala 代码制作 JDBC 代码接口。JDBC 的 API 不是为函数式语言设计的,因此您肯定需要一些可变/命令式代码来帮助弥合差距。这实际上只是阻力最小的路径的问题。
如果您只是构建一个一对一的地图,那么MapBuilder
. Scala 包含Builder
用于其大多数数据结构的类,这些类使用临时的、私有的、可变的结构来尽可能高效地构建不可变的结构。代码看起来像:
val builder = Map.newBuilder[Int, Int]
while(result.next()) {
val SomeExtractor(one, two) = result
builder += one -> two
}
return builder.result
但是,您实际上是在构建 MultiMap - 从键到多个值的映射。ScalaMultiMap
在其标准库中确实有一个特点,但它并不适合您的用例。它是可变的,并且将值存储在 mutable Set
s 中而不是List
s 中,所以我们现在将忽略它。
Scala 的标准库groupBy
在它的 trait 上确实有一个方法,它Traversable
或多或少地完成了你正在寻找的事情。我们有 aResultSet
而不是 a Traversable
,但原则上我们可以编写一些胶水代码来包装ResultSet
a Traversable
,并利用现有的代码。类似于以下内容:
// strm has side effects, caused by rs.next - only ever call it once, and re-use result if needed.
def strm: Stream[(Int, Int)] = if (rs.next) SomeExtractor.unapply(rs).get #:: strm else Stream.empty
return strm.groupBy(_._1)
这会起作用,但我们有一个关于副作用的可怕警告,而且我们实际上并没有获得任何性能。如果您查看Traversable.groupBy
(参见 GitHub 上的代码)的源代码,它实际上与您做的事情几乎相同——Map
使用我们的数据构建一个可变的,然后Map
在最后将其转换为不可变的。
我认为你已经得到的方法接近最优 - 只是 return map.toMap
。
哦,我假设 SomeExtractor 提取了一对Int
s。