35

同じタイプの2つのリストを比較するkotlin equals関数に出くわしました。データクラスを持つ純粋な Kotlin では問題なく動作します。

コールバック メソッドが X 秒の時間間隔でオブジェクトのリストを返す Kotlin プロジェクトで Java ライブラリを使用しています。呼び出しごとに古いリストと新しいリストを比較しようとしていますが、項目が同じで等しい場合でも equals は false を返します。

val mOldList: MutableList<MyObject>()? = null

override fun updatedList(list: MutableList<MyObject>){
    // other code
    if (mOldList.equals(list)) // false everytime
}

これはライブラリからの Java の equals メソッドによるものですか?

リスト比較の代替案をいただければ幸いです。

4

12 に答える 12

13

ジップの使用

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       
    }
}
于 2019-06-18T14:52:26.150 に答える
9

以下の実装を使用して、2 つの比較を行うことができます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
}

注: どちらの関数も、深いレベルの最初のレベルのみを比較します

于 2019-10-09T19:02:54.083 に答える
1

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=エヴァ),(id=2, name=アナ), id=3, name=エイブラハム)]

list2 = [(id=2, name=アナ), id=3, name=エイブラハム)]

deleteRepeated(list1, list2) を呼び出した後

list1 = [(id=1, name=エヴァ)]

于 2021-04-08T16:41:01.130 に答える
0

containsAll()それは、並べ替えと同等のチェックよりもはるかに遅いと言いたいです。

オンラインの Kotlin コンソールを使用してテストした結果は次のとおりです。 ここに画像の説明を入力

しかし、最速の方法はおそらくSet代わりに使用することです。(ただし、set は要素の重複を許可しません。そのため、ユース ケースに注意してください)

ここに画像の説明を入力

于 2021-03-31T12:46:11.453 に答える
0

同じ要素の同じ数を持ち、順序を気にしない2つのリストを比較したい場合の別の答え:

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
}
于 2021-03-02T08:50:29.060 に答える
0

これまでの質問と回答は主に equals/!equals に焦点を当てていますが、タイトルは比較について述べているため、<、=、> に対して -1,0,1 を返す compareTo を実装する、もう少し一般的な回答を提供します。

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
}
于 2020-12-22T18:55:51.730 に答える