How to compare two arrays in Kotlin?
Given some arrays in Kotlin
let a = arrayOf("first", "second")
val b = arrayOf("first", "second")
val c = arrayOf("1st", "2nd")
Are there built-in functions to the Kotlin std-lib that tests two arrays for (value) equality for each element?
Thus resulting in:
a.equals(b) // true
a.equals(c) // false
equals()
is actually returning false
in both cases, but maybe there are built-in functions to Kotlin that one could use?
There is the static function java.utils.Arrays.deepEquals(a.toTypedArray(), b.toTypedArray())
but I would rather prefer an instance method as it would work better with optionals.
Solution 1:
In Kotlin 1.1 you can use contentEquals
and contentDeepEquals
to compare two arrays for structural equality. e.g.:
a contentEquals b // true
b contentEquals c // false
In Kotlin 1.0 there are no "built-in functions to the Kotlin std-lib that tests two arrays for (value) equality for each element."
"Arrays are always compared using equals()
, as all other objects" (Feedback Request: Limitations on Data Classes | Kotlin Blog).
So a.equals(b)
will only return true
if a
and b
reference the same array.
You can, however, create your own "optionals"-friendly methods using extension functions. e.g.:
fun Array<*>.equalsArray(other: Array<*>) = Arrays.equals(this, other)
fun Array<*>.deepEqualsArray(other: Array<*>) = Arrays.deepEquals(this, other)
P.S. The comments on Feedback Request: Limitations on Data Classes | Kotlin Blog are worth a read as well, specifically comment 39364.
Solution 2:
Kotlin 1.1 introduced extensions for comparing arrays by content: contentEquals and contentDeepEquals.
These extensions are infix, so you can use them the following way:
val areEqual = arr1 contentEquals arr2
Solution 3:
And if you want to compare contents of two Collections
ignoring the order you can add this simple extension:
infix fun <T> Collection<T>.sameContentWith(collection: Collection<T>?)
= collection?.let { this.size == it.size && this.containsAll(it) }
...and use it like this:
a = mutableListOf<String>()
b = mutableListOf<String>()
isListsHasSameContent = a sameContentWith b
Solution 4:
For a simple equals (not deep equals!):
otherArray.size == array.size && otherArray.filter { !array.contains(it) }.isEmpty()
This code will compare the size and the items. The items are compared with .equals()
.
Solution 5:
In koltin if your array or ArrayList is type of a data Class
you can simply compare array :a and array :b
like this
if(a == b)
it will return simple boolean if it matched all the value of both arrays, but if you are matching other-than data data Class
then you can use this extension to compare it with single value
fun <T> Array<T>.isEqual(comparable: Array<T>): Boolean {
var isChanged = true
if (this.size == comparable.size) {
for (index in 0 until comparable.size) {
if (this[index] != comparable[index]) {
isChanged = false
break
}
}
} else {
isChanged = false
}
return isChanged
}
then you can use your array
val a = arrayOf("first", "second")
val b = arrayOf("first", "second")
println(a.isEqual(b)) //true
a[0] = "third"
println(a.isEqual(b)) //false