使代码更具功能性

时间:2014-08-05 09:39:34

标签: java scala functional-programming

这是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) }

1 个答案:

答案 0 :(得分:1)

此代码基于java.sql.ResultSet,但该模式也适用于您的情况。

选项1:提供foreach方法

您可以像这样定义一个类:

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()

选项2:扩展迭代器

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等。