我可以在多个线程中拆分kotlin集合中的mapIndexed工作吗?

时间:2019-03-12 01:28:35

标签: android kotlin

我正在为我的应用程序问题寻找解决方法。
我的应用程序正在生成一百万个点的图表,为此,我要保存一个字符串,其中所有点都用会议室数据库中的空白分隔。

话虽这么说,我正在加载这个点的字符串,使用mapIndex将其拆分为在所有点上放置一个索引,如下所示:

val map = mutableMapOf<Float, Float>()
            signal.split(" ").mapIndexed { index, signal ->
                signal.toFloatOrNull()?.let { floatSignal ->
                    map[index.toFloat()] = floatSignal
                }
            }

使用此代码,我可以在图表上显示所有点,但是当处理一百万个点(超过三秒)时,此操作mapIndexed太慢了
    我的问题是,有一种方法可以在多线程上拆分mapIndexed然后加入结果?抱歉,如果有点难以理解,我不是母语人士

1 个答案:

答案 0 :(得分:1)

并行运行map的问题是您可能会丢失列表的顺序。这是forEach循环的示例,该循环将并行执行

import java.util.*
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors


private fun getExecutor(threads: Int) = Executors.newFixedThreadPool(threads)
private fun ExecutorService.run(runnables: List<() -> Unit>) {
    val jobs = runnables.map {
        submit(it)
    }
    jobs.forEach {
        it.get()
    }
}

private val _executorMap = mutableMapOf<Int, ExecutorService>()

fun <T> Iterable<T>.forEachParallel(threads: Int = Runtime.getRuntime().availableProcessors(), block: (T) -> Unit) {

    val executor = _executorMap.getOrPut(threads) { getExecutor(threads) }

    val list: List<() -> Unit> = (0 until size).map { i ->
        { block(get(i)) }
    }

    executor.run(list)
}

或者,您可以使用RxJava

private val _executorMap = mutableMapOf<Int, Scheduler>()
private fun getScheduler(threads: Int) =
    _executorMap.getOrPut(threads) { Schedulers.from(Executors.newFixedThreadPool(threads)) }

fun <T> Iterable<T>.forEachParallel(threads: Int = Runtime.getRuntime().availableProcessors(), block: (T) -> Unit) {

    Flowable.fromIterable(this)
        .parallel(threads)
        .runOn(getScheduler(threads))
        .map(block)
        .sequential()
        .blockingSubscribe()

如果您确实需要此命令,则可以轻松地修改这2个功能以跟踪索引。您可以像这样使用它:

 bigList.forEachParallel { 
        val result = someComputation(it)
        newList.add(result)
    }