簡體   English   中英

使代碼更具功能性

[英]Make code be more in functional-style

這是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”和“ filter”,所以我想知道為什么這行不通:

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

該代碼基於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等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM