我试图用Stream替换我的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()
注意:
使用MoveToNext
将光标移动到下一行。 如果光标已经超过结果集中的最后一个条目,则此方法将返回false。
答案 0 :(得分:2)
假设您有一个条目。你产生了元组
(song, false)
扔掉它。这显然不好。即使那里没有另一首歌曲你想要保留这首歌!所以你可以试试一个选项 - 如果有的话加载一首歌,如果没有则加载。您还必须区别对待第一个元素,因为moveToFirst
与moveToNext
不同。像这样:
def loadSong = Song(
cursor.getLong(c(BaseColumns._ID)),
cursor.getString(c(MediaColumns.TITLE))
)
if (cursor.moveToFirst) {
val songs = Stream(Some(loadSong)) ++
Stream.continually(if (cursor.moveToNext()) Some(loadSong) else None)
songs.flatten.toList
}
请注意,您实际上并未在此处使用流的流畅性,因此您也可以使用Iterator.continually
。
注意:我可能会将包装逻辑移到someLong
并生成类似的内容:
def loadSong(b: Boolean) = if (!b) None else Some(Song(
cursor.getLong(c(BaseColumns._ID)),
cursor.getString(c(MediaColumns.TITLE))
))
val songs = Stream(loadSong(cursor.moveToFirst())) ++
Stream.continually(loadSong(cursor.moveToNext())
songs.flatten.toList
或者,根据我个人图书馆的方法:
def optIn[A](b: Boolean)(a: => A) = if (b) Some(a) else None
来自之前的普通loadSong
val songs = Stream(optIn(cursor.moveToFirst)(loadSong)) ++
Stream.continually(optIn(cursor.moveToNext)(loadSong))
songs.flatten.toList
可能是最紧凑和可读的。 (一旦你知道如何阅读optIn
。)
答案 1 :(得分:1)
你的光标是一种迭代器,不太方便。因此,作为Rex Kerr答案的替代方案,您可以抽象出cursor
到Iterator
(或Stream
)之间的整个转换,这样您就可以像对待光标一样迭代这样:
def loadSong(c: Cursor) = (
c.getLong(c(BaseColumns._ID)),
c.getString(c(MediaColumns.TITLE))
)
cursor.map(loadSong).toList
为此,您只需要从Cursor
到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")
}
这使得代码简短易读。