假设我有一个包含两个实例的类:
class Car(val id: Int, val color: Color, val pistons: Int, val spoiler: Boolean)
val audi = Car(1234, Color.BLUE, 8, false)
val bmw = Car(4321, Color.WHITE, 6, false)
现在我想检查一些属性的相等性(不是所有的-在这种情况下我会使用一个数据类(
fun looksSimilar(a: Car, b: Car) = a.color == b.color && a.spoiler == b.spoiler
我现在正在寻找一种进行比较的方法:
- 对于更通用的对象
T
及其属性 - 更地道的说法是:没有人愿意阅读大量的平等支票
- 同样快
我提出了以下建议:
fun <T> Pair<T, T>.equalIn(vararg arguments: (T) -> Any?) =
arguments.toList().all { it(first) == it(second) }
这让我可以把上面的支票写为
val looksSimilar = (audi to bmw).equalIn({it.color}, {it.spoiler})
有人知道更好(例如更清洁/更快(的解决方案吗?
我的用例如下:
我正在写一个带有多个RecyclerView's
(=显示列表的奇特视图(的Android应用程序
每个RecyclerView
都有一个ListAdapter
(负责底层列表(
每个ListAdapter
都需要一个DiffUtil.ItemCallback
(用于比较新旧项目以及启动视图中的适当更改(
val callback = object : DiffUtil.ItemCallback<Car>() {
override fun areItemsTheSame(oldItem: Car, newItem: Car): Boolean
// usually checks for id, e.g. oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: Car, newItem: Car): Boolean
// checks if two items look the same.
// Used for fancy enter/exit animations afaik.
// e.g. (oldItem to newItem).equalIn({it.color}, {it.spoiler})
}
在浏览StackOverflow历史时,我再次发现了这个问题,它让我的大脑发痒,所以我想了想。我仍然坚持我的观点,我更喜欢显式if检查(更容易理解IMO,性能最快(,但如果我必须用扩展函数来做,我宁愿使用列表而不是对(允许两个以上的输入(,并且我会在调用站点使用Lambda的参考语法,使其更简洁:
fun <T> List<T>.equalIn(vararg arguments: (T) -> Any?): Boolean {
if (isEmpty()) return false
val argumentsList = arguments.toList()
return all { item -> argumentsList.all { it(item) == it(first()) } }
}
fun main() {
val audi = Car(1234, Color.BLUE, 8, false)
val bmw = Car(4321, Color.BLUE, 6, false)
println(listOf(audi, bmw).equalIn(Car::color, Car::spoiler))
}