Custom equality comparator for set operation in Kotlin

50 Views Asked by At

As mentioned here: Efficient way to compare an partition two collections in Kotlin I am working on a Kotlin application that needs to compare lists of Json objects. To find the elements that are common between the existing data and the incoming data, I was hoping to use the intersect (https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/intersect.html) function. The problem is, my incoming data and existing data are do not contain objects of the same class. They DO have some common fields that I can use to compare them, but I can't see a good way to define the comparison operation for the intersect function. I don't want to override 'equals' in my data classes since I only want to change the equality behaviour for this specific use case.

Is there some way to do this in Kotlin that I'm just not seeing?

1

There are 1 best solutions below

1
k314159 On

You could define a class that holds the common fields that you need to be compared:

data class CommonFields private constructor(fieldA: Int, fieldB: String) {
    val originalInstanceA: ClassA? = null
    val originalInstanceB: ClassB? = null

    constructor(originalInstanceA: ClassA) : this(
        originalInstanceA.fieldA, originalInstanceA.fieldB
    ) {
        this.originalInstanceA = originalInstanceA
    }

    constructor(originalInstanceB: ClassB) : this(
        originalInstanceB.fieldA, originalInstanceB.fieldB
    ) {
        this.originalInstanceB = originalInstanceB
    }
}

Then you can map the two lists:

val commonFieldsA = listA.map { CommonFields(it) }
val commonFieldsB = listB.map { CommonFields(it) }

And now you can find the intersection:

commonFieldsA intersect commonFieldsB

The reason this works is that the equals method generated for the data class uses only those fields in the primary constructor and ignored other fields (the references to the original instances in this case).