在科特林中使用比较器
Using comparator in kotlin
我是 kotlin 新手,如何使用 Collections
比较对象
Collections.sort(list,myCustomComparator)
我们如何在 kotlin 中编写 MyCustomComparator
方法?
private final Comparator<CustomObject> myCustomComparator = (a, b) -> {
if (a == null && b == null) {
return 0;
} else if (a == null) {
return -1;
} else if (b == null) {
return 1;
}
};
这几乎与 Java 中的方法相同:
private val myCustomComparator = Comparator<CustomObject> { a, b ->
when {
(a == null && b == null) -> 0
(a == null) -> -1
else -> 1
}
}
if else if else ...
被单个 Kotlin when
取代,以提高代码的可读性。
在 Kotlin 中使用 Comparator
对列表进行排序也可以这样写:
val customObjects = listOf(CustomObject(), CustomObject())
customObjects.sortedWith(myCustomComparator)
您可以将 SAM conversion 与 lambda 一起使用(因为 Comparator
是一个 Java 接口,Kotlin 将允许您这样做)或匿名 class 对象.
使用 lambda 它将如下所示:
val customComparator = Comparator<CustomObject> { a, b ->
if (a == null && b == null) {
return 0;
} else if (a == null) {
return -1;
} else if (b == null) {
return 1;
}
}
和匿名class版本:
val customComparator = object: Comparator<CustomObject> {
override fun compare(a: CustomObject, b: CustomObject): Int {
if (a == null && b == null) {
return 0;
} else if (a == null) {
return -1;
} else if (b == null) {
return 1;
}
}
}
在 Kotlin 中有更好的方法对集合进行排序 - 您可以像这样使用扩展函数 sortedWith
:
list.sortedWith(Comparator { s1, s2 ->
when {
s1 == null && s2 == null -> 0
s1 == null -> -1
else -> 1
}
})
但请记住,这将 return 复制 列表。
根据其他答案,相当直接的翻译可让您对列表进行排序,例如:
fun myCustomComparator() = Comparator<CustomObject>{ a, b ->
when {
(a == null && b == null) -> 0
(a == null) -> -1
else -> 1
}
}
现在,这里没有任何内容取决于您的 CustomObject
。所以让它变得通用是微不足道的,所以它可以处理任何类型:
fun <T> nullsFirstComparator() = Comparator<T>{ a, b ->
when {
(a == null && b == null) -> 0
(a == null) -> -1
else -> 1
}
}
但是,这里存在一些潜在的问题。
主要是不一致。 Comparator
的一般合同在 Java docs:
中详细说明
The implementor must ensure that sgn(compare(x, y)) == -sgn(compare(y, x))
for all x and y
(不幸的是,Kotlin docs 没有提到任何这些。真可惜他们没有达到 Java 的标准。)
然而,上面的比较器并没有这样做;如果 a 和 b 非空,则 compare(a, b)
和 compare(b, a)
都是 1!
这很可能会导致问题;例如,根据 sort() 方法的编码方式,它可能会使列表未排序,或者永远不会完成。或者,如果您将它用于排序的地图,地图可能无法 return 它的某些值,或者永远不会完成。
这可以通过添加第四个案例来解决:
fun <T> nullsFirstComparator() = Comparator<T>{ a, b ->
when {
(a == null && b == null) -> 0
(a == null) -> -1
(b == null) -> 1
else -> 0
}
}
现在比较器是一致的;空值总是在非空值之前。
但它仍然有一个不受欢迎的特性:所有非空值现在都被视为等价的,并且不能在它们内部进行排序。一般来说,没有办法解决这个问题,因为 Kotlin 不知道如何比较两个任意对象的顺序。但是有两种方法可以告诉它如何。
一种方法是将其限制为具有自然顺序的对象,即实现 Comparable
interface. (Once again, the Java docs 的对象可以更好地解释这一点。)
fun <T : Comparable<T>> nullsFirstComparator() = Comparator<T>{ a, b ->
when {
(a == null && b == null) -> 0
(a == null) -> -1
(b == null) -> 1
else -> a.compareTo(b)
}
}
但是,如果您使用标准库 kotlin.comparisons.compareValues()
函数,则可以简化:
fun <T : Comparable<T>> nullsFirstComparator()
= Comparator<T>{ a, b -> compareValues(a, b) }
另一个是自己提供一个排序——你可以通过提供另一个 Comparator
来处理非空比较:
fun <T> nullsFirstComparator(comparator: Comparator<T>) = Comparator<T>{ a, b ->
when {
(a == null && b == null) -> 0
(a == null) -> -1
(b == null) -> 1
else -> c.compare(a, b)
}
}
但是你不需要自己写,因为 Kotlin 标准库中已经有了它,因为 kotlin.comparisons.nullsFirst()
!
考虑@Alexander的回答后,代码可以写成
private val MyCustomComparator = Comparator<MyObject> { a, b ->
when {
a == null && b == null -> return@Comparator 0
a == null -> return@Comparator -1
b == null -> return@Comparator 1
else -> return@Comparator 0
}
}
我是 kotlin 新手,如何使用 Collections
Collections.sort(list,myCustomComparator)
我们如何在 kotlin 中编写 MyCustomComparator
方法?
private final Comparator<CustomObject> myCustomComparator = (a, b) -> {
if (a == null && b == null) {
return 0;
} else if (a == null) {
return -1;
} else if (b == null) {
return 1;
}
};
这几乎与 Java 中的方法相同:
private val myCustomComparator = Comparator<CustomObject> { a, b ->
when {
(a == null && b == null) -> 0
(a == null) -> -1
else -> 1
}
}
if else if else ...
被单个 Kotlin when
取代,以提高代码的可读性。
在 Kotlin 中使用 Comparator
对列表进行排序也可以这样写:
val customObjects = listOf(CustomObject(), CustomObject())
customObjects.sortedWith(myCustomComparator)
您可以将 SAM conversion 与 lambda 一起使用(因为 Comparator
是一个 Java 接口,Kotlin 将允许您这样做)或匿名 class 对象.
使用 lambda 它将如下所示:
val customComparator = Comparator<CustomObject> { a, b ->
if (a == null && b == null) {
return 0;
} else if (a == null) {
return -1;
} else if (b == null) {
return 1;
}
}
和匿名class版本:
val customComparator = object: Comparator<CustomObject> {
override fun compare(a: CustomObject, b: CustomObject): Int {
if (a == null && b == null) {
return 0;
} else if (a == null) {
return -1;
} else if (b == null) {
return 1;
}
}
}
在 Kotlin 中有更好的方法对集合进行排序 - 您可以像这样使用扩展函数 sortedWith
:
list.sortedWith(Comparator { s1, s2 ->
when {
s1 == null && s2 == null -> 0
s1 == null -> -1
else -> 1
}
})
但请记住,这将 return 复制 列表。
根据其他答案,相当直接的翻译可让您对列表进行排序,例如:
fun myCustomComparator() = Comparator<CustomObject>{ a, b ->
when {
(a == null && b == null) -> 0
(a == null) -> -1
else -> 1
}
}
现在,这里没有任何内容取决于您的 CustomObject
。所以让它变得通用是微不足道的,所以它可以处理任何类型:
fun <T> nullsFirstComparator() = Comparator<T>{ a, b ->
when {
(a == null && b == null) -> 0
(a == null) -> -1
else -> 1
}
}
但是,这里存在一些潜在的问题。
主要是不一致。 Comparator
的一般合同在 Java docs:
The implementor must ensure that
sgn(compare(x, y)) == -sgn(compare(y, x))
for all x and y
(不幸的是,Kotlin docs 没有提到任何这些。真可惜他们没有达到 Java 的标准。)
然而,上面的比较器并没有这样做;如果 a 和 b 非空,则 compare(a, b)
和 compare(b, a)
都是 1!
这很可能会导致问题;例如,根据 sort() 方法的编码方式,它可能会使列表未排序,或者永远不会完成。或者,如果您将它用于排序的地图,地图可能无法 return 它的某些值,或者永远不会完成。
这可以通过添加第四个案例来解决:
fun <T> nullsFirstComparator() = Comparator<T>{ a, b ->
when {
(a == null && b == null) -> 0
(a == null) -> -1
(b == null) -> 1
else -> 0
}
}
现在比较器是一致的;空值总是在非空值之前。
但它仍然有一个不受欢迎的特性:所有非空值现在都被视为等价的,并且不能在它们内部进行排序。一般来说,没有办法解决这个问题,因为 Kotlin 不知道如何比较两个任意对象的顺序。但是有两种方法可以告诉它如何。
一种方法是将其限制为具有自然顺序的对象,即实现 Comparable
interface. (Once again, the Java docs 的对象可以更好地解释这一点。)
fun <T : Comparable<T>> nullsFirstComparator() = Comparator<T>{ a, b ->
when {
(a == null && b == null) -> 0
(a == null) -> -1
(b == null) -> 1
else -> a.compareTo(b)
}
}
但是,如果您使用标准库 kotlin.comparisons.compareValues()
函数,则可以简化:
fun <T : Comparable<T>> nullsFirstComparator()
= Comparator<T>{ a, b -> compareValues(a, b) }
另一个是自己提供一个排序——你可以通过提供另一个 Comparator
来处理非空比较:
fun <T> nullsFirstComparator(comparator: Comparator<T>) = Comparator<T>{ a, b ->
when {
(a == null && b == null) -> 0
(a == null) -> -1
(b == null) -> 1
else -> c.compare(a, b)
}
}
但是你不需要自己写,因为 Kotlin 标准库中已经有了它,因为 kotlin.comparisons.nullsFirst()
!
考虑@Alexander的回答后,代码可以写成
private val MyCustomComparator = Comparator<MyObject> { a, b ->
when {
a == null && b == null -> return@Comparator 0
a == null -> return@Comparator -1
b == null -> return@Comparator 1
else -> return@Comparator 0
}
}