我遇到了kotlin equals函数来比较两个相同类型的列表。它对于带有数据类的纯Kotlin很好用。
我在Kotlin项目中使用Java库,其中的回调方法以X秒的时间间隔返回对象列表。尝试针对每个调用将旧列表与新列表进行比较,但是即使项目相同且相等,equals也会返回false。
val mOldList: MutableList<MyObject>()? = null
override fun updatedList(list: MutableList<MyObject>){
// other code
if (mOldList.equals(list)) // false everytime
}
这是因为Java的来自库的equals方法吗?
列表比较的替代建议将是有益的。
答案 0 :(得分:2)
Java列表实现equals
方法,并且如果两个列表包含相同顺序的相同元素,则两个列表定义为相等。我猜想,您的equals
类中缺少MyObject
方法。
答案 1 :(得分:2)
:使用扩展功能的简短版本:
fun List<*>.deepEquals(other : List<*>) =
this.size == other.size && this.mapIndexed { index, element -> element == other[index] }.all { it }
您可以这样使用它:
listOf("Hola", "Mundo").deepEquals(listOf("Hello", "World"))
答案 2 :(得分:1)
您可以使用以下实现比较两个Collection
:
infix fun <T> Collection<T>.deepEqualTo(other: Collection<T>): Boolean {
// check collections aren't same
if (this !== other) {
// fast check of sizes
if (this.size != other.size) return false
val areNotEqual = this.asSequence()
.zip(other.asSequence())
// check this and other contains same elements at position
.map { (fromThis, fromOther) -> fromThis == fromOther }
// searching for first negative answer
.contains(false)
if (areNotEqual) return false
}
// collections are same or they are contains same elements with same order
return true
}
或忽略订单变体:
infix fun <T> Collection<T>.deepEqualToIgnoreOrder(other: Collection<T>): Boolean {
// check collections aren't same
if (this !== other) {
// fast check of sizes
if (this.size != other.size) return false
val areNotEqual = this.asSequence()
// check other contains next element from this
.map { it in other }
// searching for first negative answer
.contains(false)
if (areNotEqual) return false
}
// collections are same or they are contains same elements
return true
}
注意:这两个函数仅比较第一级深度
答案 3 :(得分:1)
如果您不必担心两个列表中元素的顺序,而您的目标是只检查两个列表中元素完全相同,没有其他元素,则可以考虑两个相互containsAll
的调用,例如:
var list1 = mutableListOf<String>()
var list2 = mutableListOf<String>()
if(list1.containsAll(list2) && list2.containsAll(list1)) {
//both lists are of the same elements
}
答案 4 :(得分:0)
您可以遍历一个列表并从第二个列表中检查相应的位置值。请以下面的示例为参考。
var list1 = mutableListOf<String>()
var list2 = mutableListOf<String>()
list1.forEachIndexed { i, value ->
if (list2[i] == value)
{
// your implementaion
}
}
此外,您还可以过滤列表以获取更改的值。
var list1 = mutableListOf<String>()
var list2 = mutableListOf<String>()
val changedList = list1.filterIndexed { i, value ->
list2[i] != value)
}
答案 5 :(得分:0)
使用zip
zip
返回一个从该数组的元素和另一个具有相同索引的数组构建的对的列表。返回的列表具有最短集合的长度。
fun listsEqual(list1: List<Any>, list2: List<Any>): Boolean {
if (list1.size != list2.size)
return false
val pairList = list1.zip(list2)
return pairList.all { (elt1, elt2) ->
elt1 == elt2
}
}
答案 6 :(得分:0)
如果您的自定义对象基于list1 == list2
(它会自动覆盖您的等号),您也可以无需任何额外的工作就可以调用data class
。
答案 7 :(得分:0)
您可以使用数组和contentDeepEquals
:
infix fun <T> Array<out T>.contentDeepEquals(
other: Array<out T>
): Boolean
JVM
1.1
@JvmName("contentDeepEqualsInline") infix fun <T> Array<out T>.contentDeepEquals(
other: Array<out T>
): Boolean
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/content-deep-equals.html
答案 8 :(得分:0)
到目前为止的问题和答案主要集中在 equals/!equals 上,但由于标题谈到比较,我将给出一个稍微通用的答案,实现 compareTo 为 <、= 返回 -1,0,1, >
fun <T: Comparable<T>> Iterable<T>.compareTo(other: Iterable<T>): Int {
val otherI = other.iterator()
for (e in this) {
if (!otherI.hasNext()) return 1 // other has run out of elements, so `this` is larger
val c = e.compareTo(otherI.next())
if (c != 0) return c // found a position with a difference
}
if (otherI.hasNext()) return -1 // `this` has run out of elements, but other has some more, so other is larger
return 0 // they're the same
}
答案 9 :(得分:0)
如果您想比较两个列表,它们具有相同数量的相同元素,并且不关心顺序,则另一个答案:
infix fun <T> List<T>.elementEquals(other: List<T>): Boolean {
if (this.size != other.size) return false
val tracker = BooleanArray(this.size)
var counter = 0
root@ for (value in this) {
destination@ for ((i, o) in other.withIndex()) {
if (tracker[i]) {
continue@destination
} else if (value?.equals(o) == true) {
counter++
tracker[i] = true
continue@root
}
}
}
return counter == this.size
}
答案 10 :(得分:0)
想说 containsAll()
比排序和检查相等要慢得多。
但最快的方法可能是使用 Set
代替。
(但是,set 不允许重复元素。所以要小心你的用例)
答案 11 :(得分:0)
当我想与 kotlin 上的列表进行比较时,我喜欢这种方式
data class Element(val id: String, val name: String)
var list1 = mutableListOf<Element>()
var list2 = mutableListOf<Element>()
fun deleteRepeated(
list1: List<Element>,
newElementsList: List<Element>
): List<FileInfo> {
return list2.filterNot { isTheSameID(it, list1) }
}
private fun isTheSameID(element: Element, list1: List<FileInfo>): Boolean {
list1.forEach {
if (element.id == it.id){
return true
}
}
return false
}
list1 = [(id=1, name=Eva),(id=2, name=Ana), id=3, name=Abraham)]
list2 = [(id=2, name=Ana), id=3, name=Abraham)]
调用deleteRepeated(list1, list2)后
list1 = [(id=1, name=Eva)]