Rajnikant B
Rajnikant B

Reputation: 126

How to create a sorted merged list from two diffrent ArrayList of Objects based on a common value field in Kotlin?

I have two ArrayLists of different Data classes as given below:

class Record{
    var id: Long = 0
    var RecordId: Int = 0
    var Record: String? = null
    var title: String? = null
    var description: String? = null
    var longDate: Long = 0
}

class Type{
    var id: Long = 0
    var typeId: Int = 0
    var subTypeId: Int = 0
    var typeString: String? = null
    var longDate: Long = 0
}

var recordsList: ArrayList<Record>
var typesList: ArrayList<Type>

Now, I want a merged list of these two which will be sorted based on a common field in both the Objects i.e. longDate. I have tried .associate , sortedBy, sortedWith(compareBy<>) etc. but could not achieve the desired result.

Here, also there is one point to note is that while comparing the two lists it is possible that one on them may be empty.

Upvotes: 0

Views: 432

Answers (2)

Tenfour04
Tenfour04

Reputation: 93629

This will produce a List<Any> with all items sorted by longDate:

(recordsList + typesList)
    .sortedBy { 
        when (it) {
            is Record -> it.longDate
            is Type -> it.longDate
            else -> error("")
        }
    }

Or you might consider creating an interface that has val longDate: Long that both of these classes implement. Then you wouldn't need the when expression, and your List would be of the type of the interface.

Upvotes: 2

AlexT
AlexT

Reputation: 2964

Something like this should work, but I personally think that it is quite the code smell. There is no guarantee that Record.longDate is truly the same type as Type.longDate (we know that it is, since we create the model, but the compiler would never know).

val result = (recordsList + typesList).sortedBy {
        when(it){
            is Record -> it.longDate
            is Type -> it.longDate
            else -> error("incompatible list element $it")
        }
    }

And it would work something like this: (I've removed some parameters from the models as they don't really count here)

    
fun main() {
    
    val recordsList = listOf(Record().apply { longDate = 5 }, Record().apply { longDate = 3})
    val typesList =  listOf(Type().apply { longDate = 3 }, Type().apply { longDate = 2 })
    
    val result = (recordsList + typesList).sortedBy {
        when(it){
            is Record -> it.longDate
            is Type -> it.longDate
            else -> error("incompatible list element $it")
        }
    }
    
    result.forEach{
        println(it.toString())
    }
    
}


class Record{
        var longDate: Long = 0
    override fun toString(): String {
        return "Record(longDate=$longDate)"
    }
}

class Type{
    var longDate: Long = 0
    override fun toString(): String {
        return "Type(longDate=$longDate)"
    }
}

This will output:

Type(longDate=2)
Record(longDate=3)
Type(longDate=3)
Record(longDate=5)

Doing it in a more generic way, so that you can create a fun where you state which property to be used from each object type would most likely use reflection, which I'd avoid at all costs.

So I would definitely consider if one object can inherit the other, or create an interface, or anything else.

I'll end with 2 questions: why no constructors? why ArrayList and not list?

Upvotes: 1

Related Questions