这是实现binarySearch方法的Kotlin代码:
public fun <T> List<T>.binarySearch(element: T, comparator: Comparator<in 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 = comparator.compare(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
}
为什么Comparator的类型为而不是T?
我们使用in仅仅是为了可读性吗?或者在上面的代码片段中有一个实际的用途,如果我们不使用“in”,事情就不会工作?
2条答案
按热度按时间ttcibm8c1#
使用Comparator而不是Comparator允许方法接受在T的超类型上操作的Comparator。
这很有用,因为它使binarySearch方法更加灵活,并且可以处理列表中的元素是搜索元素类型的子类型的情况。例如,如果T是Animal,并且列表包含Dog和Cat对象,则即使搜索元素是Dog或Cat,该方法仍可以使用对Animal对象进行操作的Comparator。
如果我们使用Comparator,binarySearch方法将只接受专门对T对象进行操作的Comparator,这将限制其灵活性。
因此,在这种情况下,in关键字不仅仅用于可读性目的,它确保方法可以接受在T的超类型上操作的Comparator。
idfiyjo82#
从理论上讲,它可以使系统更灵活。
这是因为
Comparator<Fruit>
是Comparator<in Orange>
的子类型,但它不是Comparator<Orange>
的子类型。然而,在这个例子中的用处是非常有限的,你可以调用:
或者完全省略泛型类型以允许推断它,它会工作得很好,因为您的
List<Orange>
也是List<Fruit>
。如果二进制搜索函数返回找到的实际项,那么它返回
T
,那么额外的灵活性将更有用,因为T
可以解析为Orange
而不是Fruit
,所以返回的项将是更具体的类型。