这是Java-Scala代码:
class MyDbManager extends SQLiteOpenHelper ....
val cursor = new MyDbManager().getReadableDatabase.query(....)
val result = new ArrayList[MyItem] //???
//?????????
if (cursor.moveToFirst()) {
do {
result + parse(cursor)
} while (cursor.moveToNext())
}
//?????????
cursor.close()
result
我想要做的是不能使用任何可变集合和不可变的集合与可变变量。我想做这样的事情:
val result = if (cursor.moveToFirst()) {
do { parse(cursor) } while (cursor.moveToNext())
}
你明白了:不使用任何冗余变量,特别是可变的。当然,上面的代码不会编译。
如果有可能,我该怎么做?我希望尽可能简单地不带涉及任何第三方库。
更新: "对于"有人建议。因为" for"转换为" map"和"过滤"在我的情况下,我想知道,为什么这不起作用:
if.(cursor.moveToFirst()) cursor.filter(_.moveToNext()).map { x => parse(x) }
答案 0 :(得分:1)
此代码基于java.sql.ResultSet
,但该模式也适用于您的情况。
您可以像这样定义一个类:
class Cursor[T](rs: ResultSet)(f: Row => T) {
def foreach(g: T => Unit) {
val row = new Row(rs)
while (rs.next()) {
g(f(row))
}
}
}
它有两个参数:
f
,它为每一行生成一个实例。因此,在迭代期间,构建基于当前行的实例。 Cursor
类提供了foreach
方法。所以它可以用于“理解”:
val cursor = Cursor(rs) {
row =>
Person(row.getString(1), row.getString(2))
}
for {
person <- cursor
} {
println(person)
}
为了能够使用函数{ ... }
的{{1}}语法,需要一个伴随对象:
f
使用表示结果集行的包装类object Cursor {
def apply[T](rs: ResultSet)(f: Row => T) = {
new Cursor(rs)(f)
}
}
,因为该函数不应该看到基础结果集的某些方法(如Row
)。
next()
class Row(rs: ResultSet) {
def getString(n: Int) = rs.getString(n)
def getInt(n: Int) = rs.getInt(n)
// ... more getters for other types
}
您也可以在“理解”中使用class CursorWithIterator[T](rs: ResultSet)(f: Row => T) extends Iterator[T] {
private val row = new Row(rs)
override def hasNext = rs.next()
override def next() = f(row)
}
。它使您可以访问完整的集合API,如Iterator
等。