0

while ループを Stream に置き換えようとしましたが、Stream バージョンを使用すると、最後の要素が常に欠落しています。欠落している理由は理解していると思いますが、これを修正する方法がわかりません。提案はありますか?また、これを行うより良い方法はありますか?ありがとう

ストリームの使用:

if(cursor.moveToFirst) {
val result = Stream.continually((
  Song(
    cursor.getLong(c(BaseColumns._ID)),
    cursor.getString(c(MediaColumns.TITLE))     
  ),
  cursor.moveToNext))
.takeWhile(_._2)
.map(_._1)
result.toList
}

ここでは while ループ バージョンが正常に動作します。

cursor.moveToFirst()
var i = 0
var list: List[Song] = List.empty
while (i < cursor.getCount()) {
  val s = Song(
    cursor.getLong(c(BaseColumns._ID)),
    cursor.getString(c(MediaColumns.TITLE)))
  i = i + 1
  list = list :+ s
  cursor.moveToNext()

ノート:

次へ移動

カーソルを次の行に移動します。カーソルが結果セットの最後のエントリをすでに通過している場合、このメソッドは false を返します。

4

2 に答える 2

1

カーソルは一種のイテレータですが、あまり便利ではありません。cursorしたがって、Rex Kerr の回答の代わりに、Iterator(または)間の変換全体を抽象化して、Stream次のようにカーソルを反復処理する方法を得ることができます。

def loadSong(c: Cursor) = (
  c.getLong(c(BaseColumns._ID)),
  c.getString(c(MediaColumns.TITLE))     
)

cursor.map(loadSong).toList

そのためには、各反復でカーソルが適切な状態 (読み取り可能な状態) にあるyourCursorから an への暗黙的な変換が必要です。Iterator[Cursor]実装は次のようになります。

implicit def cursor2Iterator(c: Cursor): Iterator[Cursor] = if (c.moveToFirst) 
  new NonEmptyCursorIterator(c) else Iterator.empty

sealed class NonEmptyCursorIterator(private val c: Cursor) extends Iterator[Cursor] {
    private[this] var hasNext0 = true // always has at least one element

    def hasNext() = {
      if (!hasNext0) hasNext0 = c.moveToNext
      hasNext0
    }

    def next(): Cursor = if (hasNext()) {
      hasNext0 = false 
      c
    } else throw new NoSuchElementException("hasNext() is false")
}

これにより、短くて読みやすいコードが作成されます。

于 2013-07-21T16:24:39.057 に答える