【问题标题】:Make code be more in functional-style让代码更具函数式风格
【发布时间】:2014-08-05 09:39:33
【问题描述】:

这里是 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”。因为在我的例子中“for”转换为“map”和“filter”,我想知道为什么这不起作用:

if.(cursor.moveToFirst()) cursor.filter(_.moveToNext()).map { x => parse(x) }

【问题讨论】:

  • 这会很困难:数据库游标本质上是一种命令式构造。如果你想避免命令式循环,你可以使用 fold 传递光标。
  • 或者,如果您希望使用filter,您可以使用始终解析为true 的谓词来获取查询的所有行。
  • 尝试使用scala.collection.Iterator trait 定义一个扩展游标类的新类。然后,您只需要定义 hasNextnext() 方法,就可以使用 for-comp

标签: java scala functional-programming


【解决方案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)
}

为了能够对函数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
}

选项 2:扩展迭代器

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

您也可以在“理解”中使用Iterator。它使您可以访问完整的集合 API,例如 map 等。

【讨论】:

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