我正在玩扩展功能,并尝试在列表上执行binarySearch功能。我意识到已经有一个内置于Kotlin的扩展功能。但是,它很慢: -
public fun <T: Comparable<T>> List<T?>.binarySearch(element: T?, fromIndex: Int = 0, toIndex: Int = size): Int {
rangeCheck(size, fromIndex, toIndex)
var low = fromIndex
var high = toIndex - 1
while (low <= high) {
val mid = (low + high).ushr(1) // safe from overflows
val midVal = get(mid)
val cmp = compareValues(midVal, element)
if (cmp < 0)
low = mid + 1
else if (cmp > 0)
high = mid - 1
else
return mid // key found
}
return -(low + 1) // key not found
}
我编辑了函数并删除了函数调用(compareValues),替换函数更快
test_buildin_binary_search 8s35m
test_binary_search 584ms
^根据我的测试,我会把它附上。
新的: -
fun rangeCheck(size: Int, fromIndex: Int, toIndex: Int) {
when {
fromIndex > toIndex -> throw IllegalArgumentException("fromIndex ($fromIndex) is greater than toIndex ($toIndex).")
fromIndex < 0 -> throw IndexOutOfBoundsException("fromIndex ($fromIndex) is less than zero.")
toIndex > size -> throw IndexOutOfBoundsException("toIndex ($toIndex) is greater than size ($size).")
}
}
fun <T : Comparable<T>> binarySearch(list: List<T?>, element: T?, fromIndex: Int = 0, toIndex: Int = list.size): Int {
rangeCheck(list.size, fromIndex, toIndex)
var low = fromIndex
var high = toIndex - 1
while (low <= high) {
val mid = (low + high).ushr(1) // safe from overflows
val midVal = list.get(mid)
val cmp = element?.compareTo(midVal as T) as Int
if (cmp < 0)
low = mid + 1
else if (cmp > 0)
high = mid - 1
else
return mid // key found
}
return -(low + 1) // key not found
}
到目前为止,它不是扩展功能。但我相信内部函数调用是使它变慢的原因。
Q1。为什么compareValues不是内联函数?可能是由于设计决定?内联它并不总是一个好主意?
Q2。是否有一个关键字,让程序员可以自由地内联函数“f1”,例如f1不是内联函数?
我的意思是为什么没有像“inlineit”这样的关键字,它被用作: -
fun f1() {
println("something")
}
fun main() {
inlineit f1() // line 1
f1() // line 2
}
在这种情况下,只有当我们在名称前面使用关键字inlineit时才会内联f1(),在上面的代码中,第1行中的代码f1()是内联的,而第2行则不是。
junit测试: -
class BinarySearchTests() {
private val max = 10_000_000
private val times = 10_000_000
private val largNumbers = (0..max).toList()
private val r = Random(System.currentTimeMillis())
@Test
fun test_binary_search() {
var found = false
repeat(times) {
val item = r.nextInt(max)
val r = binarySearch(largNumbers, item)
if (r != null) found = true
}
assert(found)
}
@Test
fun test_buildin_binary_search() {
var found = false
repeat(times) {
val item = r.nextInt(max)
val r = largNumbers.binarySearch(item)
if (r != -1) found = true
}
assert(found)
}
}
谢谢