Как отсортировать 144 000 файлов по lastModified () и length () в Kotlin за секунду? - PullRequest
0 голосов
/ 06 января 2020

У меня есть следующий ArrayList файла.

    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 ГБ. Я хочу отсортировать их по 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
              }

          }


Ссылка на библиотеку, которую я использовал для сортировки файлов, выполняется в фоновом потоке: https://github.com/Kotlin/anko

Для выполнения приведенного выше кода требуется 3-5 секунд. , Я хочу, чтобы это было сделано в течение секунды. Как решить эту проблему? Я делаю это для android.

При необходимости я готов изменить API для выполнения фоновой задачи

1 Ответ

0 голосов
/ 08 января 2020

Я хочу, чтобы это было сделано за секунду

Коротко: в общем случае это невозможно. Файловая система (на Android или на любой другой ОС) может быть перегружена, поэтому эта операция может иногда приостанавливать работу вашего приложения. Обратите внимание на это.

Однако вы можете ускорить код, используя следующий алгоритм:

  • Параллельное чтение метаданных файла
  • Сортировка файлов по этим результатам.

Пожалуйста, используйте пример ниже. Обратите внимание, что он выполняет много параллельных операций ввода-вывода.

Преимущества этого решения:

  • Метаданные считываются из отдельного контекста (который имеет ограничение потока, чтобы избежать чрезмерного использования ввода-вывода)
  • Метаданные файла X читаются только один раз.
  • Алгоритм сортировки работает только с оперативной памятью, например, использует готовые данные, что ограничивает доступ к вводу-выводу.
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)
        }
    }
}
...