如何在一秒钟内在 Kotlin 中通过 lastModified() 和 length() 对 144,000 个文件进行排序?
How to sort 144,000 files by lastModified() and length() in Kotlin within a second?
我有以下 ArrayList of File。
var a = ArrayList<File>()
var b = ArrayList<File>()
var c = ArrayList<File>()
var d = ArrayList<File>()
var e = ArrayList<File>()
应用程序启动后,上述 ArrayList 将包含超过 144,000 个文件。所有这些加起来的总大小接近 3.5 GB。我想在一秒钟内按 lastModified() 或 length() 对它们进行排序,并将修改后的 ArrayList 更新到 RecyclerView。
为了排序方便我把上面的ArrayList变成了一个Array<ArrayList<File>>
如下:
val mList = arrayOf(a,b,c,d,e)
为了加快速度,我在后台线程中执行所有操作。代码:
doAsync {
mList.forEach{ index ->
index.sortByDescending { it.lastModified() }
}
activityUiThread {
setRecyclerViewAdapter() // Update RecyclerView with new sorted files
}
}
Link 到我在后台线程中使用排序文件的库:https://github.com/Kotlin/anko
以上代码执行需要将近3-5秒。我希望这在一秒钟内完成。如何解决这个问题?我这样做是为了 android。
如果需要,我准备更改 API 以执行后台任务
I want this to be done within a second
短:一般情况下是不可能的。文件系统(在 Android 或任何其他 OS 上)可能会过载,因此此操作有时会暂停您的应用程序。请注意这一点。
但是您可以使用以下算法加速代码:
- 并行读取文件元数据
- 根据这些结果对文件进行排序。
请使用下面的示例。请注意,它执行大量并行 IO 操作。
此解决方案的优势:
- 元数据从单独的上下文中读取(有线程限制,以避免 IO 过度使用)
- 文件 X 的元数据只读取一次。
- 排序算法仅适用于操作内存,例如它使用就绪数据,这减少了 IO 访问。
suspend fun sortFiles(files: Iterable<File>): List<File> {
val metadataReadTasks: List<Deferred<FileWithMetadata>> = withContext(Dispatchers.IO)
{
files.map { file ->
async {
FileWithMetadata(file)
}
}
}
val metadatas: List<FileWithMetadata> = metadataReadTasks.awaitAll()
return metadatas
.sorted()
.map {
it.file
}
}
private class FileWithMetadata(
val file: File
) : Comparable<FileWithMetadata> {
private val lastModified = file.lastModified()
private val length = file.length()
override fun compareTo(other: FileWithMetadata): Int {
return when (other.length) {
this.length -> other.lastModified.compareTo(this.lastModified)
else -> other.length.compareTo(this.length)
}
}
}
我有以下 ArrayList of File。
var a = ArrayList<File>()
var b = ArrayList<File>()
var c = ArrayList<File>()
var d = ArrayList<File>()
var e = ArrayList<File>()
应用程序启动后,上述 ArrayList 将包含超过 144,000 个文件。所有这些加起来的总大小接近 3.5 GB。我想在一秒钟内按 lastModified() 或 length() 对它们进行排序,并将修改后的 ArrayList 更新到 RecyclerView。
为了排序方便我把上面的ArrayList变成了一个Array<ArrayList<File>>
如下:
val mList = arrayOf(a,b,c,d,e)
为了加快速度,我在后台线程中执行所有操作。代码:
doAsync {
mList.forEach{ index ->
index.sortByDescending { it.lastModified() }
}
activityUiThread {
setRecyclerViewAdapter() // Update RecyclerView with new sorted files
}
}
Link 到我在后台线程中使用排序文件的库:https://github.com/Kotlin/anko
以上代码执行需要将近3-5秒。我希望这在一秒钟内完成。如何解决这个问题?我这样做是为了 android。
如果需要,我准备更改 API 以执行后台任务
I want this to be done within a second
短:一般情况下是不可能的。文件系统(在 Android 或任何其他 OS 上)可能会过载,因此此操作有时会暂停您的应用程序。请注意这一点。
但是您可以使用以下算法加速代码:
- 并行读取文件元数据
- 根据这些结果对文件进行排序。
请使用下面的示例。请注意,它执行大量并行 IO 操作。
此解决方案的优势:
- 元数据从单独的上下文中读取(有线程限制,以避免 IO 过度使用)
- 文件 X 的元数据只读取一次。
- 排序算法仅适用于操作内存,例如它使用就绪数据,这减少了 IO 访问。
suspend fun sortFiles(files: Iterable<File>): List<File> {
val metadataReadTasks: List<Deferred<FileWithMetadata>> = withContext(Dispatchers.IO)
{
files.map { file ->
async {
FileWithMetadata(file)
}
}
}
val metadatas: List<FileWithMetadata> = metadataReadTasks.awaitAll()
return metadatas
.sorted()
.map {
it.file
}
}
private class FileWithMetadata(
val file: File
) : Comparable<FileWithMetadata> {
private val lastModified = file.lastModified()
private val length = file.length()
override fun compareTo(other: FileWithMetadata): Int {
return when (other.length) {
this.length -> other.lastModified.compareTo(this.lastModified)
else -> other.length.compareTo(this.length)
}
}
}