过滤,减去或分组 - 最有效的是什么? (科特林)

时间:2018-05-17 13:13:47

标签: kotlin

例如,我们有一个列表,我们想用特定的谓词分成两部分。

首先,我们可以使用filterfilterNot

val trueList = list.filter(predicate)
val falseList = list.filterNot(predicate)

其次,我们可以使用filtersubtract

val trueList = list.filter(predicate)
val falseList = list.subtract(trueList)

第三,我们可以使用groupBy

val groupBy = list.groupBy(predicate)
val trueList = groupBy[true]
val falseList = groupBy[false]

什么是最有效,最快捷的方式?我们可以用其他一些功能来做到这一点吗?

我认为subtract的第二个选项是最糟糕的,我是对的吗?

1 个答案:

答案 0 :(得分:1)

因此,我尝试了解哪个选项最快:filtersubtractgroupBypartition(感谢Marko Topolnik提示)。我使用measureTimeMillis来了解每个选项的已用时间:

private fun checkTime(list: List<Int>, predicate: (Int) -> Boolean) {
    var sum = 0L
    repeat(times) { sum += checkPartition(list, predicate) }
    println("partition: ${sum/times}")

    sum = 0L
    repeat(times) { sum += checkFilter(list, predicate) }
    println("filter: ${sum/times}")

    sum = 0L
    repeat(times) { sum += checkSubtract(list, predicate) }
    println("subtract: ${sum/times}")

    sum = 0L
    repeat(times) { sum += checkGroupBy(list, predicate) }
    println("group by: ${sum/times}")
}


private fun checkGroupBy(list: List<Int>, predicate: (Int) -> Boolean): Long {
    return measureTimeMillis {
        val groupBy = list.groupBy(predicate)
        val falseList = groupBy[false]
        val trueList = groupBy[true]
    }
}

private fun checkSubtract(list: List<Int>, predicate: (Int) -> Boolean): Long {
    return measureTimeMillis {
        val trueList = list.filter(predicate)
        val falseList = list.subtract(trueList)
    }
}

private fun checkFilter(list: List<Int>, predicate: (Int) -> Boolean): Long {
    return measureTimeMillis {
        val trueList = list.filter(predicate)
        val falseList = list.filterNot(predicate)
    }
}

private fun checkPartition(list: List<Int>, predicate: (Int) -> Boolean): Long {
    return measureTimeMillis {
        val pair = list.partition(predicate)
        val trueList = pair.first
        val falseList = pair.second
    }
}

我用10次重复检查了这个谓词:

val predicate = { it: Int -> it % 2 == 0 }

使用不同大小的列表:

var list = (1..1_000_000).toList()
checkTime(list, predicate)
  

分区:16   过滤器:21   减去:81   分组:18

list = (1..2_000_000).toList()
checkTime(list, predicate)
  

分区:30   过滤器:42   减去:241   分组:36

list = (1..3_000_000).toList()
checkTime(list, predicate)
  

分区:35   过滤器:59   减去:233   分组:63

因此,partition是将列表分为两部分的非常好的选择。

请告诉我,如果我做错了什么。