如何在一秒钟内在 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)
        }
    }
}