为什么Kotlin的binarySearch方法中Comparator要用in T而非T?
Kotlin二分查找方法中Comparator的作用解析
先看实现代码:
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而非Comparator?
这里的in是Kotlin的逆变关键字,核心作用是放宽比较器的类型限制。Comparator的compare方法是接收输入参数的逻辑,对于输入型参数,逆变允许我们传入一个能处理T父类的比较器。
举个实际例子:假设T是Dog类(继承自Animal),我们有一个通用的Comparator<Animal>用来比较所有动物的属性(比如体重),这个比较器完全能用来比较Dog。如果方法参数写的是Comparator<T>,这个Comparator<Animal>就无法传入;但用Comparator<in T>就可以,因为Animal是Dog的父类,符合in T的类型要求,这样就能复用更通用的比较器,提升方法的灵活性。
不用in会导致功能无法正常运行吗?
这不是单纯为了可读性,不用in不会让方法本身的查找逻辑失效,但会大幅限制它的使用场景。
比如刚才的场景,当你需要用针对T父类的比较器来查找List<T>中的元素时,没有in的话编译器会直接报错,不允许传入该比较器。但从方法逻辑来看,这个比较器是完全兼容的——因为compare方法只需要接收T类型的参数,而父类比较器的compare方法本来就能接收T(因为T是父类的子类)。所以不用in的话,方法功能本身没问题,但能支持的使用场景会少很多,灵活性大打折扣。
内容的提问来源于stack exchange,提问作者Hack123
相关产品推荐
相关产品推荐

